Compare commits

...

28 Commits

Author SHA1 Message Date
37bf4bc0b0 Release 5.17.0 2024-07-09 21:15:18 -05:00
5d60ba36b7 Support for 1.21.2 2024-07-09 21:07:47 -05:00
68d2e2915e Bells always drops themselves (#4802) 2024-07-07 15:20:45 -05:00
20f5741ed7 Bowl: Add fuel return value (#6384) 2024-07-05 17:41:22 -05:00
23b2b75acf Merge pull request #6380 from pmmp/dependabot/composer/phpunit/phpunit-10.5.24 2024-07-04 21:16:19 +00:00
25ea9b2218 Bump phpunit/phpunit from 10.3.5 to 10.5.24
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.3.5 to 10.5.24.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.5.24/ChangeLog-10.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.3.5...10.5.24)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 10:53:54 +00:00
77db7a8941 Merge pull request #6381 from pmmp/dependabot/composer/symfony/filesystem-6.4.9 2024-07-01 10:53:02 +00:00
af4294295b Bump symfony/filesystem from 6.4.7 to 6.4.9
Bumps [symfony/filesystem](https://github.com/symfony/filesystem) from 6.4.7 to 6.4.9.
- [Release notes](https://github.com/symfony/filesystem/releases)
- [Changelog](https://github.com/symfony/filesystem/blob/7.1/CHANGELOG.md)
- [Commits](https://github.com/symfony/filesystem/compare/v6.4.7...v6.4.9)

---
updated-dependencies:
- dependency-name: symfony/filesystem
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 10:19:24 +00:00
585aee9386 Fixed an oopsie from 5ef247620a
I added it to the wrong set of artifacts :(
2024-06-13 18:58:32 +01:00
433bd6a8aa 5.16.1 is next 2024-06-13 18:55:21 +01:00
22a1549998 Release 5.16.0 2024-06-13 18:55:18 +01:00
0ec8465fcf shut! 2024-06-13 18:43:10 +01:00
f121654452 Assemble 1.21.0 2024-06-13 18:41:41 +01:00
08c6e63aac Bump phpstan/phpstan from 1.10.67 to 1.11.2 (#6352)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.67 to 1.11.2.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.67...1.11.2)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-31 17:01:51 +01:00
4c418b4318 Remove unnecessary return statement (#6350) 2024-05-31 16:54:50 +01:00
fb9a74e879 gitignore files generated by install-local-protocol.sh 2024-05-13 11:52:31 +01:00
554775841e Added script for linking local versions of Bedrock* deps for testing 2024-05-13 11:48:23 +01:00
373dd9938c Update composer dependencies 2024-05-13 11:37:32 +01:00
f772bb7384 WoodenStairs can be a fuel (#6345) 2024-05-13 09:34:18 +01:00
5ef247620a Attach permission doc to every release 2024-05-07 12:46:31 +01:00
1b082f99e9 DefaultPermissions: fixed typo 2024-05-07 12:34:42 +01:00
9b6a0c9945 Bump phpstan/phpstan-strict-rules from 1.5.3 to 1.5.5 (#6335)
Bumps [phpstan/phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules) from 1.5.3 to 1.5.5.
- [Release notes](https://github.com/phpstan/phpstan-strict-rules/releases)
- [Commits](https://github.com/phpstan/phpstan-strict-rules/compare/1.5.3...1.5.5)

---
updated-dependencies:
- dependency-name: phpstan/phpstan-strict-rules
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:41:59 +01:00
ab3be50b49 Bump phpstan/phpstan from 1.10.66 to 1.10.67 (#6337)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.66 to 1.10.67.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.66...1.10.67)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:41:50 +01:00
27dc43f131 Bump shivammathur/setup-php from 2.30.2 to 2.30.4 (#6339)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.30.2 to 2.30.4.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.30.2...2.30.4)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:41:40 +01:00
d67f5a5c6f Bump symfony/filesystem from 6.4.6 to 6.4.7 (#6342)
Bumps [symfony/filesystem](https://github.com/symfony/filesystem) from 6.4.6 to 6.4.7.
- [Release notes](https://github.com/symfony/filesystem/releases)
- [Changelog](https://github.com/symfony/filesystem/blob/7.0/CHANGELOG.md)
- [Commits](https://github.com/symfony/filesystem/compare/v6.4.6...v6.4.7)

---
updated-dependencies:
- dependency-name: symfony/filesystem
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:41:28 +01:00
ed158f8a1b Server: include uptime in crash restart throttle message
this makes it clearer why the wait duration is chosen instead of it looking random.
2024-04-29 16:36:14 +01:00
d70a7d34a7 Living: don't knockback or do hurt FX when attacked during cooldown
players were switching from a weaker tool to a stronger one to get double knockback in PvP.
while it's intended that we don't cancel the second attack during hit cooldown if the damage is
higher (the first damage is subtracted to prevent doubling up), we don't want them to get double
knockback.
this behaviour now matches vanilla to the best of my observations.

Come at me PvP community... I know some people are going to hate this change
2024-04-29 15:51:43 +01:00
be6754494f 5.15.1 is next 2024-04-25 11:52:31 +01:00
37 changed files with 462 additions and 255 deletions

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.30.2
uses: shivammathur/setup-php@2.30.4
with:
php-version: 8.2

View File

@ -20,7 +20,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.30.2
uses: shivammathur/setup-php@2.30.4
with:
php-version: ${{ matrix.php-version }}
@ -76,6 +76,9 @@ jobs:
${{ steps.php-binary-url.outputs.PHP_BINARY_URL }} \
> build_info.json
- name: Generate core permission doc for doc.pmmp.io
run: php tools/generate-permission-doc.php rst
- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
@ -84,11 +87,12 @@ jobs:
${{ github.workspace }}/PocketMine-MP.phar
${{ github.workspace }}/start.*
${{ github.workspace }}/build_info.json
${{ github.workspace }}/core-permissions.rst
- 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 }}

View File

@ -28,7 +28,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.30.2
uses: shivammathur/setup-php@2.30.4
with:
php-version: 8.2
tools: php-cs-fixer:3.49

3
.gitignore vendored
View File

@ -53,3 +53,6 @@ Documentation/*
# php-cs-fixer
/.php_cs.cache
/.php-cs-fixer.cache
# install-local-protocol.sh
/composer-local-protocol.*

26
changelogs/5.16.md Normal file
View File

@ -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`.

25
changelogs/5.17.md Normal file
View File

@ -0,0 +1,25 @@
# 5.17.0
Released 10th July 2024.
**For Minecraft: Bedrock Edition 1.21.2**
This is a support release for Minecraft: Bedrock Edition 1.21.2.
**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.2.
- Removed support for earlier versions.
## API
### `pocketmine\player`
- The following methods have been added:
- `public function closeAllForms() : void` - closes the current viewing form and forms in queue.
## Fixes
- Bowl can now be used as fuel.
- Bells always drops themselves even when using an incompatible tool.

View File

@ -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": "~32.1.0+bedrock-1.21.2",
"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.66",
"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": {

197
composer.lock generated
View File

@ -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": "7cddeede03046e04932d117c76898baf",
"content-hash": "d459605b85f247204988a879982aab50",
"packages": [
{
"name": "adhocore/json-comment",
@ -67,25 +67,25 @@
},
{
"name": "brick/math",
"version": "0.11.0",
"version": "0.12.1",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478"
"reference": "f510c0a40911935b77b86859eb5223d58d660df1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478",
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478",
"url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1",
"reference": "f510c0a40911935b77b86859eb5223d58d660df1",
"shasum": ""
},
"require": {
"php": "^8.0"
"php": "^8.1"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "5.0.0"
"phpunit/phpunit": "^10.1",
"vimeo/psalm": "5.16.0"
},
"type": "library",
"autoload": {
@ -105,12 +105,17 @@
"arithmetic",
"bigdecimal",
"bignum",
"bignumber",
"brick",
"math"
"decimal",
"integer",
"math",
"mathematics",
"rational"
],
"support": {
"issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.11.0"
"source": "https://github.com/brick/math/tree/0.12.1"
},
"funding": [
{
@ -118,20 +123,20 @@
"type": "github"
}
],
"time": "2023-01-15T23:15:59+00:00"
"time": "2023-11-29T23:19:16+00:00"
},
{
"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",
@ -142,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",
@ -168,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",
@ -194,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": "32.1.0+bedrock-1.21.2",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "dc7606a9f778eeeeccfae393bd58e0b62ec6f85a"
"reference": "bb23db51365bdc91d3135c3885986a691ae1cb44"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/dc7606a9f778eeeeccfae393bd58e0b62ec6f85a",
"reference": "dc7606a9f778eeeeccfae393bd58e0b62ec6f85a",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/bb23db51365bdc91d3135c3885986a691ae1cb44",
"reference": "bb23db51365bdc91d3135c3885986a691ae1cb44",
"shasum": ""
},
"require": {
@ -222,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"
@ -240,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/32.1.0+bedrock-1.21.2"
},
"time": "2024-04-05T17:53:35+00:00"
"time": "2024-07-10T01:38:43+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -829,20 +834,20 @@
},
{
"name": "ramsey/uuid",
"version": "4.7.5",
"version": "4.7.6",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
"reference": "91039bc1faa45ba123c4328958e620d382ec7088"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
"reference": "91039bc1faa45ba123c4328958e620d382ec7088",
"shasum": ""
},
"require": {
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11",
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
"ext-json": "*",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
@ -905,7 +910,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.7.5"
"source": "https://github.com/ramsey/uuid/tree/4.7.6"
},
"funding": [
{
@ -917,20 +922,20 @@
"type": "tidelift"
}
],
"time": "2023-11-08T05:53:05+00:00"
"time": "2024-04-27T21:32:50+00:00"
},
{
"name": "symfony/filesystem",
"version": "v6.4.6",
"version": "v6.4.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3"
"reference": "b51ef8059159330b74a4d52f68e671033c0fe463"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/9919b5509ada52cc7f66f9a35c86a4a29955c9d3",
"reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463",
"reference": "b51ef8059159330b74a4d52f68e671033c0fe463",
"shasum": ""
},
"require": {
@ -938,6 +943,9 @@
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"require-dev": {
"symfony/process": "^5.4|^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
@ -964,7 +972,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v6.4.6"
"source": "https://github.com/symfony/filesystem/tree/v6.4.9"
},
"funding": [
{
@ -980,20 +988,20 @@
"type": "tidelift"
}
],
"time": "2024-03-21T19:36:20+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": {
@ -1043,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": [
{
@ -1059,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": {
@ -1123,7 +1131,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0"
},
"funding": [
{
@ -1139,22 +1147,22 @@
"type": "tidelift"
}
],
"time": "2024-01-29T20:11:03+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": {
@ -1162,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",
@ -1192,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": [
{
@ -1200,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",
@ -1380,16 +1389,16 @@
},
{
"name": "phpstan/phpstan",
"version": "1.10.66",
"version": "1.11.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "94779c987e4ebd620025d9e5fdd23323903950bd"
"reference": "0d5d4294a70deb7547db655c47685d680e39cfec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/94779c987e4ebd620025d9e5fdd23323903950bd",
"reference": "94779c987e4ebd620025d9e5fdd23323903950bd",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/0d5d4294a70deb7547db655c47685d680e39cfec",
"reference": "0d5d4294a70deb7547db655c47685d680e39cfec",
"shasum": ""
},
"require": {
@ -1432,13 +1441,9 @@
{
"url": "https://github.com/phpstan",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
"type": "tidelift"
}
],
"time": "2024-03-28T16:17:31+00:00"
"time": "2024-05-24T13:23:04+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
@ -1494,16 +1499,16 @@
},
{
"name": "phpstan/phpstan-strict-rules",
"version": "1.5.3",
"version": "1.5.5",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "568210bd301f94a0d4b1e5a0808c374c1b9cf11b"
"reference": "2e193a07651a6f4be3baa44ddb21d822681f5918"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/568210bd301f94a0d4b1e5a0808c374c1b9cf11b",
"reference": "568210bd301f94a0d4b1e5a0808c374c1b9cf11b",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/2e193a07651a6f4be3baa44ddb21d822681f5918",
"reference": "2e193a07651a6f4be3baa44ddb21d822681f5918",
"shasum": ""
},
"require": {
@ -1537,22 +1542,22 @@
"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.5.3"
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.5"
},
"time": "2024-04-06T07:43:25+00:00"
"time": "2024-04-19T15:12:26+00:00"
},
{
"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": {
@ -1609,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": [
{
@ -1617,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",
@ -1864,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": {
@ -1913,7 +1918,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "10.3-dev"
"dev-main": "10.5-dev"
}
},
"autoload": {
@ -1945,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": [
{
@ -1961,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",

21
install-local-protocol.sh Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
echo "--- Installing BedrockProtocol, BedrockData, BedrockBlockUpgradeSchema, BedrockItemUpgradeSchema dependencies from local repositories."
echo "--- This allows you to perform integration tests using PocketMine-MP, without immediately publishing new versions of these libraries."
cp composer.json composer-local-protocol.json
cp composer.lock composer-local-protocol.lock
export COMPOSER=composer-local-protocol.json
composer config repositories.bedrock-protocol path ../deps/BedrockProtocol
composer config repositories.bedrock-data path ../deps/BedrockData
composer config repositories.bedrock-block-upgrade-schema path ../deps/BedrockBlockUpgradeSchema
composer config repositories.bedrock-item-upgrade-schema path ../deps/BedrockItemUpgradeSchema
composer require pocketmine/bedrock-protocol:*@dev pocketmine/bedrock-data:*@dev pocketmine/bedrock-block-upgrade-schema:*@dev pocketmine/bedrock-item-upgrade-schema:*@dev
composer install
echo "--- Local dependencies have been successfully installed."
echo "--- This script does not modify composer.json. To go back to the original dependency versions, simply run 'composer install'."

View File

@ -1666,9 +1666,11 @@ class Server{
$this->isRunning = false;
//Force minimum uptime to be >= 120 seconds, to reduce the impact of spammy crash loops
$spacing = ((int) $this->startTime) - time() + 120;
$uptime = time() - ((int) $this->startTime);
$minUptime = 120;
$spacing = $minUptime - $uptime;
if($spacing > 0){
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
echo "--- Uptime {$uptime}s - waiting {$spacing}s to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
sleep($spacing);
}
@Process::kill(Process::pid());

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "5.15.0";
public const BASE_VERSION = "5.17.0";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "stable";

View File

@ -150,6 +150,10 @@ final class Bell extends Transparent{
}
}
public function getDropsForIncompatibleTool(Item $item) : array{
return [$this->asItem()];
}
private function isValidFaceToRing(int $faceHit) : bool{
return match($this->attachmentType){
BellAttachmentType::CEILING => true,

View File

@ -28,6 +28,10 @@ use pocketmine\block\utils\WoodTypeTrait;
class WoodenStairs extends Stair{
use WoodTypeTrait;
public function getFuelTime() : int{
return $this->woodType->isFlammable() ? 300 : 0;
}
public function getFlameEncouragement() : int{
return 5;
}

View File

@ -236,6 +236,7 @@ final class CraftingManagerFromDataHelper{
}
$outputs[] = $output;
}
//TODO: check unlocking requirements - our current system doesn't support this
$result->registerShapelessRecipe(new ShapelessRecipe(
$inputs,
$outputs,
@ -262,6 +263,7 @@ final class CraftingManagerFromDataHelper{
}
$outputs[] = $output;
}
//TODO: check unlocking requirements - our current system doesn't support this
$result->registerShapedRecipe(new ShapedRecipe(
$recipe->shape,
$inputs,

View File

@ -23,7 +23,9 @@ declare(strict_types=1);
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<string> $shape
* @phpstan-param array<string, RecipeIngredientData> $input
* @phpstan-param list<ItemStackData> $output
* @phpstan-param list<RecipeIngredientData> $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;
}
}

View File

@ -23,7 +23,9 @@ declare(strict_types=1);
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<RecipeIngredientData> $input
* @phpstan-param list<ItemStackData> $output
* @phpstan-param list<RecipeIngredientData> $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;
}
}

View File

@ -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";

View File

@ -59,7 +59,6 @@ final class BlockStateNames{
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 @@ final class BlockStateNames{
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 @@ final class BlockStateNames{
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 @@ final class BlockStateNames{
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";

View File

@ -62,12 +62,6 @@ final class BlockStateStringValues{
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 @@ final class BlockStateStringValues{
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 @@ final class BlockStateStringValues{
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";

View File

@ -144,9 +144,11 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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 @@ final class BlockTypeNames{
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";

View File

@ -552,6 +552,16 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
//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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$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 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
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())

View File

@ -32,6 +32,7 @@ use pocketmine\block\CopperStairs;
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\Stair;
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 @@ final class BlockStateDeserializerHelper{
->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 @@ final class BlockStateDeserializerHelper{
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

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
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 @@ final class BlockStateReader{
};
}
/** @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)){

View File

@ -107,10 +107,9 @@ final class BlockStateSerializerHelper{
->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 @@ final class BlockStateSerializerHelper{
->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 @@ final class BlockStateSerializerHelper{
->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{

View File

@ -44,7 +44,6 @@ use pocketmine\block\utils\DripleafState;
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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
* @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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
});
});
$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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$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 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
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))

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
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 @@ final class BlockStateWriter{
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){

View File

@ -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";

View File

@ -555,26 +555,33 @@ abstract class Living extends Entity{
return;
}
$this->attackTime = $source->getAttackCooldown();
if($this->attackTime <= 0){
//this logic only applies if the entity was cold attacked
if($source instanceof EntityDamageByChildEntityEvent){
$e = $source->getChild();
if($e !== null){
$motion = $e->getMotion();
$this->knockBack($motion->x, $motion->z, $source->getKnockBack(), $source->getVerticalKnockBackLimit());
$this->attackTime = $source->getAttackCooldown();
if($source instanceof EntityDamageByChildEntityEvent){
$e = $source->getChild();
if($e !== null){
$motion = $e->getMotion();
$this->knockBack($motion->x, $motion->z, $source->getKnockBack(), $source->getVerticalKnockBackLimit());
}
}elseif($source instanceof EntityDamageByEntityEvent){
$e = $source->getDamager();
if($e !== null){
$deltaX = $this->location->x - $e->location->x;
$deltaZ = $this->location->z - $e->location->z;
$this->knockBack($deltaX, $deltaZ, $source->getKnockBack(), $source->getVerticalKnockBackLimit());
}
}
}elseif($source instanceof EntityDamageByEntityEvent){
$e = $source->getDamager();
if($e !== null){
$deltaX = $this->location->x - $e->location->x;
$deltaZ = $this->location->z - $e->location->z;
$this->knockBack($deltaX, $deltaZ, $source->getKnockBack(), $source->getVerticalKnockBackLimit());
if($this->isAlive()){
$this->doHitAnimation();
}
}
if($this->isAlive()){
$this->applyPostDamageEffects($source);
$this->doHitAnimation();
}
}

View File

@ -25,5 +25,7 @@ namespace pocketmine\item;
class Bowl extends Item{
//TODO: check fuel
public function getFuelTime() : int{
return 200;
}
}

View File

@ -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 @@ class InventoryManager{
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 @@ class InventoryManager{
$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 @@ class InventoryManager{
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 @@ class InventoryManager{
//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;

View File

@ -54,6 +54,7 @@ use pocketmine\network\mcpe\handler\SessionStartPacketHandler;
use pocketmine\network\mcpe\handler\SpawnResponsePacketHandler;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ClientboundCloseFormPacket;
use pocketmine\network\mcpe\protocol\ClientboundPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
@ -1170,6 +1171,10 @@ class NetworkSession{
return $this->sendDataPacket(ModalFormRequestPacket::create($id, json_encode($form, JSON_THROW_ON_ERROR)));
}
public function onCloseAllForms() : void{
$this->sendDataPacket(ClientboundCloseFormPacket::create());
}
/**
* Instructs the networksession to start using the chunk at the given coordinates. This may occur asynchronously.
* @param \Closure $onCompletion To be called when chunk sending has completed.

View File

@ -36,6 +36,7 @@ use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipeBlockName;
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 @@ final class CraftingDataCache{
$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 @@ final class CraftingDataCache{
$nullUUID,
$typeTag,
50,
$noUnlockingRequirement,
$index
);
}elseif($recipe instanceof ShapedRecipe){
@ -114,6 +117,7 @@ final class CraftingDataCache{
CraftingRecipeBlockName::CRAFTING_TABLE,
50,
true,
$noUnlockingRequirement,
$index,
);
}else{

View File

@ -83,7 +83,7 @@ abstract class DefaultPermissions{
self::registerPermission(new Permission(Names::COMMAND_PLUGINS, l10n::pocketmine_permission_command_plugins()), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_SAVE_DISABLE, l10n::pocketmine_permission_command_save_disable()), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_SAVE_ENABLE, l10n::pocketmine_permission_command_save_enable()), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_SAVE_PERFORM, l10n::pocketmine_permission_command_save_enable()), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_SAVE_PERFORM, l10n::pocketmine_permission_command_save_perform()), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_SAY, l10n::pocketmine_permission_command_say()), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_SEED, l10n::pocketmine_permission_command_seed()), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_SETWORLDSPAWN, l10n::pocketmine_permission_command_setworldspawn()), [$operatorRoot]);

View File

@ -2151,6 +2151,13 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
return true;
}
/**
* Closes the current viewing form and forms in queue.
*/
public function closeAllForms() : void{
$this->getNetworkSession()->onCloseAllForms();
}
/**
* Transfers a player to another server.
*

View File

@ -51,12 +51,12 @@ use function time;
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
];

View File

@ -27,6 +27,7 @@ use PHPUnit\Framework\TestCase;
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 @@ final class BlockStateDataTest extends TestCase{
) 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
));
}
}
}

View File

@ -195,7 +195,7 @@ class ParserPacketHandler extends PacketHandler{
* @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 @@ class ParserPacketHandler extends PacketHandler{
}
}
}
$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) : []
);
}