Compare commits

...

56 Commits
5.2.1 ... 5.3.3

Author SHA1 Message Date
a1f34a460b Release 5.3.3 2023-07-24 17:29:56 +01:00
5ff03c81f8 Merge branch 'legacy/pm4' into stable 2023-07-24 17:00:13 +01:00
1c611a03e6 4.23.4 is next 2023-07-24 16:59:48 +01:00
948875b025 Release 4.23.3 2023-07-24 16:59:45 +01:00
16dfd27935 Merge branch 'legacy/pm4' into stable 2023-07-24 16:45:24 +01:00
2a4909d328 Fixed missing handling for some ContainerUIIds
SMITHING_TABLE_TEMPLATE is new in 1.20
HORSE_EQUIP was always present, but somehow got overlooked when building up that big ugly switch table
2023-07-24 16:44:01 +01:00
fd23281183 Merge branch 'legacy/pm4' into stable 2023-07-24 12:00:29 +01:00
70dd8732e2 Update build/php to pmmp/PHP-Binaries@46604f2f6a 2023-07-24 11:59:11 +01:00
cdf72563f4 Update composer dependencies 2023-07-24 11:58:50 +01:00
9ef835c82d Merge remote-tracking branch 'origin/legacy/pm4' into stable 2023-07-21 11:07:32 +01:00
d65d8c3356 Fix typo in documentation of ChunkSelector:selectChunks() (#5924) 2023-07-21 10:34:34 +01:00
9b43ddecbd Drop usages of Process:kill() with subprocesses parameter
we don't need this any more with console reader improvements, and this was not working correctly anyway.

closes #5234
2023-07-20 17:10:39 +01:00
4bdd6410db Fire: fixed support requirements
closes #5599
2023-07-20 17:00:32 +01:00
6ea7fd7d6b ShulkerBox: do not offer support for other blocks 2023-07-20 16:36:25 +01:00
5e7f18cbcf StandardEntityEventBroadcaster: suppress client-side emote messages
if users want these, they can broadcast them themselves using Server::broadcastMessage(), which will also record the message in the server log like chat

closes #5669
2023-07-20 16:20:34 +01:00
4517948297 FrostedIce: Remove non-Bedrock melting behaviour (#5486) 2023-07-19 17:12:05 +01:00
777a901932 Bump shivammathur/setup-php from 2.25.2 to 2.25.4 (#5829)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.25.2 to 2.25.4.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.25.2...2.25.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>
2023-07-19 16:37:33 +01:00
24d979bd08 Fixed /kill not properly killing the player under certain conditions, closes #4680 (#5919)
This occurs if the player had very high levels of Health Boost or other weird modifications.

It doesn't really make sense to apply damage modifiers to suicide anyway.

Really I'm doubtful that suicide should even be considered a damage type (perhaps we should add an EntitySuicideEvent), but that's a discussion for another time.
2023-07-19 16:33:16 +01:00
86810c5e1c LevelDB: clearer error message 2023-07-19 16:31:10 +01:00
b33a9690e9 LevelDB: simplify condition 2023-07-19 16:30:13 +01:00
1b9c282194 LevelDB: tolerate incorrect number of biome palettes, as long as there are enough for each real subchunk
modern versions save 24 exactly, but previous versions saved more. We don't use the excess, so it's not a problem if they are missing, but this is nonetheless non-compliant with vanilla.
2023-07-19 16:29:14 +01:00
82b75e0ccb LevelDB: Remove happy debug message 2023-07-19 15:21:47 +01:00
6c59912ed5 LevelDB: workaround 0 bpb palettes with a length prefix
this was caused by a plugin overriding the world provider.

related:
-  https://github.com/pmmp/PocketMine-MP/issues/5911
-  https://github.com/Refaltor77/CustomItemAPI/issues/68

fixes #5911
2023-07-19 15:19:33 +01:00
763241b11f Fixed burning animations for fireproof entities
creative players are not technically fireproof; they just don't take any damage from fire
2023-07-19 12:32:00 +01:00
8414c78969 Fixed netherite items burning in lava 2023-07-19 11:49:52 +01:00
4637aae621 Living: do not apply noDamageTicks to suicide damage
suicide damage is a voluntary damage source, which noDamageTicks is intended to prevent getting damaged while the player gets their bearings after (re)spawning.
2023-07-19 11:43:09 +01:00
f38aee1fc5 5.3.3 is next 2023-07-18 22:18:39 +01:00
69abd5eb53 Release 5.3.2 2023-07-18 22:18:39 +01:00
f6ee7ddc9e Merge branch 'legacy/pm4' into stable 2023-07-18 22:15:23 +01:00
cff4a8d2bc 4.23.3 is next 2023-07-18 22:14:24 +01:00
20b7e8d702 Release 4.23.2 2023-07-18 22:14:23 +01:00
c6110be051 Update BedrockProtocol dependency 2023-07-18 22:12:33 +01:00
c053742f5d Living: avoid updates of non-armor slots and armor slots which took no damage
this was also updating empty slots ...
2023-07-18 13:04:11 +01:00
0051b34797 Living: fixed turtle helmet being non-removable and spamming inventory updates
closes #5786
2023-07-18 12:58:07 +01:00
30db658d70 Bump phpunit/phpunit from 10.2.5 to 10.2.6 (#5909)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.5 to 10.2.6.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.6/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.5...10.2.6)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  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>
2023-07-18 11:34:13 +01:00
0c1bfb058a Bump phpunit/phpunit from 10.2.3 to 10.2.5 (#5898)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.3 to 10.2.5.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.5/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.3...10.2.5)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  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>
2023-07-14 17:45:36 +01:00
45d1ce9bb8 Don't mention enchantments in generic StringToTParser doc-comment (#5894) 2023-07-14 17:42:19 +01:00
f7c08dedee 5.3.2 is next 2023-07-14 13:08:58 +01:00
250d18e41b Release 5.3.1 2023-07-14 13:08:57 +01:00
86bd6777a3 4.23.2 is next 2023-07-14 13:06:26 +01:00
935df62006 Release 4.23.1 2023-07-14 13:06:26 +01:00
489a7ba365 Merge branch 'legacy/pm4' into stable 2023-07-14 13:03:14 +01:00
2709dd359c ProcessLoginTask: fixed backport errors 2023-07-14 12:37:50 +01:00
4e646d19a4 Harden login EC key validation 2023-07-14 11:55:47 +01:00
2a11762e61 Update JsonMapper dependency 2023-07-14 11:54:05 +01:00
d2f4ba74c6 Updated build/php submodule to pmmp/PHP-Binaries@e0c918d137 2023-07-13 12:59:43 +01:00
d4716ef457 5.3.1 is next 2023-07-12 14:08:08 +01:00
d630b3af7b Release 5.3.0 2023-07-12 14:07:58 +01:00
c2bb51cb37 Merge branch 'legacy/pm4' into stable 2023-07-12 13:45:37 +01:00
7e0b5cf73d 4.23.1 is next 2023-07-12 13:44:16 +01:00
e903da8998 Release 4.23.0 2023-07-12 13:44:16 +01:00
b7210755a7 1.20.10 2023-07-12 13:39:39 +01:00
f2193d1ba7 1.20.10 2023-07-12 13:23:47 +01:00
4daacb2ab7 Merge branch 'legacy/pm4' into stable 2023-07-12 12:11:36 +01:00
f7977c9668 Update build/php submodule to pmmp/PHP-Binaries@16378ffcc3 2023-07-12 12:10:09 +01:00
93d3f439bf 5.2.2 is next 2023-07-11 16:04:43 +01:00
41 changed files with 449 additions and 135 deletions

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.4
with:
php-version: 8.1

View File

@ -18,7 +18,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.4
with:
php-version: 8.1

View File

@ -173,7 +173,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.4
with:
php-version: 8.1
tools: php-cs-fixer:3.17

View File

@ -139,7 +139,7 @@ function generateBlockStateNames(BlockPaletteReport $data) : void{
fwrite($output, generateClassHeader(BlockStateNames::class));
foreach(Utils::stringifyKeys($data->seenStateValues) as $state => $values){
$constName = mb_strtoupper(preg_replace("/^minecraft:/", "", $state) ?? throw new AssumptionFailedError("This regex is not invalid"), 'US-ASCII');
$constName = mb_strtoupper(preg_replace("/^minecraft:/", "mc_", $state) ?? throw new AssumptionFailedError("This regex is not invalid"), 'US-ASCII');
fwrite($output, "\tpublic const $constName = \"$state\";\n");
}
@ -159,7 +159,7 @@ function generateBlockStringValues(BlockPaletteReport $data) : void{
continue;
}
$anyWritten = true;
$constName = mb_strtoupper(preg_replace("/^minecraft:/", "", $stateName) . "_" . $value, 'US-ASCII');
$constName = mb_strtoupper(preg_replace("/^minecraft:/", "mc_", $stateName) . "_" . $value, 'US-ASCII');
fwrite($output, "\tpublic const $constName = \"$value\";\n");
}
if($anyWritten){

45
changelogs/4.23.md Normal file
View File

@ -0,0 +1,45 @@
# 4.23.0
Released 12th July 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a support release for Minecraft: Bedrock Edition 1.20.10.
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` 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.20.10.
- Removed support for older versions.
## Fixes
- Fixed Docker image build failure due to outdated `build/php` submodule.
# 4.23.1
Released 14th July 2023.
## Fixes
- Hardened validation of JWT signing keys in `LoginPacket`.
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
# 4.23.2
Released 18th July 2023.
## Fixes
- Fixed login errors due to a new `sandboxId` field appearing in the Xbox Live authentication data in `LoginPacket`. All clients, regardless of version, are affected by this change.
# 4.23.3
Released 24th July 2023.
## Documentation
- Fixed typo in `ChunkSelector::selectChunks()` documentation.
## Fixes
- Fixed the server not stopping properly during crash conditions on *nix platforms.
- Fixed `HORSE_EQUIP` and `SMITHING_TABLE_TEMPLATE` container UI types not being handled by `ItemStackContainerIdTranslator`. This bug prevented plugins from implementing missing inventory types.
- Player emotes no longer broadcast messages to other players. This was unintended behaviour caused by a client-side behavioural change.
- Shulker boxes no longer support the placement of torches or other similar blocks.
- Fire can now be placed on upper slabs and the top of upside-down stairs.

72
changelogs/5.3.md Normal file
View File

@ -0,0 +1,72 @@
# 5.3.0
Released 12th July 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a support release for Minecraft: Bedrock Edition 1.20.10.
**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.
## Interim releases
If you're upgrading directly from 5.1.x to 5.3.x, please also read the following changelogs, as the interim releases contain important changes:
- [5.2.0](https://github.com/pmmp/PocketMine-MP/blob/5.2.0/changelogs/5.2.md#520)
## Included releases
**This release includes changes from the following releases:**
- [4.23.0](https://github.com/pmmp/PocketMine-MP/blob/4.23.0/changelogs/4.23.md#4230) - Support for Minecraft: Bedrock Edition 1.20.10
## Internals
- `BlockTypeNames`, `BlockStateNames`, `BlockStateStringValues` and `ItemTypeNames` in the `pocketmine\data\bedrock` package have BC-breaking changes to accommodate Bedrock 1.20.10.
# 5.3.1
Released 14th July 2023.
## Included releases
**This release includes changes from the following releases:**
- [4.23.1](https://github.com/pmmp/PocketMine-MP/blob/4.23.1/changelogs/4.23.md#4231) - Security fixes
## General
- Updated `build/php` submodule to pmmp/PHP-Binaries@e0c918d1379465964acefd562d9e48f87cfc2c9e.
# 5.3.2
Released 18th July 2023.
## Included releases
**This release includes changes from the following releases:**
- [4.23.2](https://github.com/pmmp/PocketMine-MP/blob/4.23.2/changelogs/4.23.md#4232) - Fix for `sandboxId`-related login errors
## Documentation
- Fixed documentation error in `StringToTParser`.
## Fixes
- Fixed turtle helmet not being able to be unequipped.
## Internals
- Armor pieces are no longer set back into the armor inventory if no change was made. This reduces the number of slot updates sent to clients, as well as avoiding unnecessary updates for armor pieces which have Unbreaking enchantments.
# 5.3.3
Released 24th July 2023.
## Included releases
**This release includes changes from the following releases:**
- [4.23.3](https://github.com/pmmp/PocketMine-MP/blob/4.23.3/changelogs/4.23.md#4233) - Various bug fixes
## Fixes
- Added a workaround for PM4 worlds with chunks corrupted by [Refaltor77/CustomItemAPI](https://github.com/Refaltor77/CustomItemAPI).
- While this was not the fault of PocketMine-MP itself, a significant number of users were affected by this problem.
- This error was not detected by PM4 due to missing validation of certain data which should not have existed in 1.12.
- An error will now be logged when this corruption is detected, but the affected chunks should otherwise load normally.
- Relaxed validation of expected 3D biome array counts per chunk in LevelDB worlds.
- Vanilla Bedrock currently saves 24 palettes (and only 24 are required), but it saved 25, 32, or 64 biome palettes per chunk in older versions.
- Core validation for these padding biomes was very strict, enforcing exact compliance with vanilla.
- Since only 24 palettes are actually required, the remaining palettes may now be omitted irrespective of the chunk version.
- An error will still be logged when this mistake is detected, but the affected chunks will otherwise load normally.
- Fixed `/kill` not working on players who had (re)spawned in the 3 seconds immediately after (re)spawning (due to `noDamageTicks`).
- Fixed `/kill` not working correctly for players with high levels of Health Boost or other health-altering effects.
- Fixed netherite items being destroyed by lava.
- Fireproof entities no longer display the burning animation when in fire or lava. This does not apply to creative players, who are immortal rather than being fireproof.
- Fixed frosted ice melting in certain conditions which didn't match vanilla Bedrock.

View File

@ -33,11 +33,11 @@
"composer-runtime-api": "^2.0",
"adhocore/json-comment": "~1.2.0",
"fgrosse/phpasn1": "~2.5.0",
"pocketmine/netresearch-jsonmapper": "~v4.2.999",
"pocketmine/bedrock-block-upgrade-schema": "~3.0.0",
"pocketmine/bedrock-data": "~2.3.0+bedrock-1.20.0",
"pocketmine/bedrock-item-upgrade-schema": "~1.3.0+bedrock-1.20.0",
"pocketmine/bedrock-protocol": "~22.0.0+bedrock-1.20.0",
"pocketmine/netresearch-jsonmapper": "~v4.2.1000",
"pocketmine/bedrock-block-upgrade-schema": "~3.1.0+bedrock-1.20.10",
"pocketmine/bedrock-data": "~2.4.0+bedrock-1.20.10",
"pocketmine/bedrock-item-upgrade-schema": "~1.4.0+bedrock-1.20.10",
"pocketmine/bedrock-protocol": "~23.0.2+bedrock-1.20.10",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/color": "^0.3.0",

87
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": "ff0fa864a7853011bf4620d870c47ac7",
"content-hash": "e14717125dd180235fb888662a48846d",
"packages": [
{
"name": "adhocore/json-comment",
@ -198,16 +198,16 @@
},
{
"name": "pocketmine/bedrock-block-upgrade-schema",
"version": "3.0.0",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
"reference": "8b72c47109e174ac7f17c3ac546748f8e49a5fdf"
"reference": "6d4ae416043337946a22fc31e8065ca2c21f472d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/8b72c47109e174ac7f17c3ac546748f8e49a5fdf",
"reference": "8b72c47109e174ac7f17c3ac546748f8e49a5fdf",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/6d4ae416043337946a22fc31e8065ca2c21f472d",
"reference": "6d4ae416043337946a22fc31e8065ca2c21f472d",
"shasum": ""
},
"type": "library",
@ -218,22 +218,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/3.0.0"
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.1.0"
},
"time": "2023-07-03T16:35:44+00:00"
"time": "2023-07-12T12:05:36+00:00"
},
{
"name": "pocketmine/bedrock-data",
"version": "2.3.1+bedrock-1.20.0",
"version": "2.4.0+bedrock-1.20.10",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
"reference": "fb89ccdc039252462d8d068a769635e24151b7e2"
"reference": "f98bd1cae46d2920058acf3b23c0bedeac79f4ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/fb89ccdc039252462d8d068a769635e24151b7e2",
"reference": "fb89ccdc039252462d8d068a769635e24151b7e2",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/f98bd1cae46d2920058acf3b23c0bedeac79f4ab",
"reference": "f98bd1cae46d2920058acf3b23c0bedeac79f4ab",
"shasum": ""
},
"type": "library",
@ -244,22 +244,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/2.3.1+bedrock-1.20.0"
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.10"
},
"time": "2023-06-13T16:42:09+00:00"
"time": "2023-07-12T11:51:54+00:00"
},
{
"name": "pocketmine/bedrock-item-upgrade-schema",
"version": "1.3.0",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
"reference": "b16c59cfae08833f180dd82f88de7c1f43bc67c9"
"reference": "60d199afe5e371fd189b21d685ec1fed6ba54230"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/b16c59cfae08833f180dd82f88de7c1f43bc67c9",
"reference": "b16c59cfae08833f180dd82f88de7c1f43bc67c9",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/60d199afe5e371fd189b21d685ec1fed6ba54230",
"reference": "60d199afe5e371fd189b21d685ec1fed6ba54230",
"shasum": ""
},
"type": "library",
@ -270,22 +270,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.3.0"
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.4.0"
},
"time": "2023-05-18T15:34:32+00:00"
"time": "2023-07-12T12:08:37+00:00"
},
{
"name": "pocketmine/bedrock-protocol",
"version": "22.0.0+bedrock-1.20.0",
"version": "23.0.2+bedrock-1.20.10",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "ceff28a0bd5d248f37fb97be3e836d536e37526e"
"reference": "69a309a2dd7dcf3ec8c316385b866397e8c2cbfd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/ceff28a0bd5d248f37fb97be3e836d536e37526e",
"reference": "ceff28a0bd5d248f37fb97be3e836d536e37526e",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/69a309a2dd7dcf3ec8c316385b866397e8c2cbfd",
"reference": "69a309a2dd7dcf3ec8c316385b866397e8c2cbfd",
"shasum": ""
},
"require": {
@ -317,9 +317,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/22.0.0+bedrock-1.20.0"
"source": "https://github.com/pmmp/BedrockProtocol/tree/23.0.2+bedrock-1.20.10"
},
"time": "2023-06-07T19:22:05+00:00"
"time": "2023-07-24T15:35:36+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -639,16 +639,16 @@
},
{
"name": "pocketmine/netresearch-jsonmapper",
"version": "v4.2.999",
"version": "v4.2.1000",
"source": {
"type": "git",
"url": "https://github.com/pmmp/netresearch-jsonmapper.git",
"reference": "f700806dec756ed825a8200dc2950ead98265956"
"reference": "078764e869e9b732f97206ec9363480a77c35532"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/netresearch-jsonmapper/zipball/f700806dec756ed825a8200dc2950ead98265956",
"reference": "f700806dec756ed825a8200dc2950ead98265956",
"url": "https://api.github.com/repos/pmmp/netresearch-jsonmapper/zipball/078764e869e9b732f97206ec9363480a77c35532",
"reference": "078764e869e9b732f97206ec9363480a77c35532",
"shasum": ""
},
"require": {
@ -687,9 +687,9 @@
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/pmmp/netresearch-jsonmapper/tree/v4.2.999"
"source": "https://github.com/pmmp/netresearch-jsonmapper/tree/v4.2.1000"
},
"time": "2023-06-01T13:43:01+00:00"
"time": "2023-07-14T10:44:14+00:00"
},
{
"name": "pocketmine/raklib",
@ -1937,16 +1937,16 @@
},
{
"name": "phpunit/phpunit",
"version": "10.2.3",
"version": "10.2.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "35c8cac1734ede2ae354a6644f7088356ff5b08e"
"reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/35c8cac1734ede2ae354a6644f7088356ff5b08e",
"reference": "35c8cac1734ede2ae354a6644f7088356ff5b08e",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1c17815c129f133f3019cc18e8d0c8622e6d9bcd",
"reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd",
"shasum": ""
},
"require": {
@ -2018,7 +2018,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.2.3"
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.6"
},
"funding": [
{
@ -2034,7 +2034,7 @@
"type": "tidelift"
}
],
"time": "2023-06-30T06:17:38+00:00"
"time": "2023-07-17T12:08:28+00:00"
},
{
"name": "sebastian/cli-parser",
@ -2546,16 +2546,16 @@
},
{
"name": "sebastian/global-state",
"version": "6.0.0",
"version": "6.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "aab257c712de87b90194febd52e4d184551c2d44"
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/aab257c712de87b90194febd52e4d184551c2d44",
"reference": "aab257c712de87b90194febd52e4d184551c2d44",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4",
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4",
"shasum": ""
},
"require": {
@ -2595,7 +2595,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.0"
"security": "https://github.com/sebastianbergmann/global-state/security/policy",
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1"
},
"funding": [
{
@ -2603,7 +2604,7 @@
"type": "github"
}
],
"time": "2023-02-03T07:07:38+00:00"
"time": "2023-07-19T07:19:23+00:00"
},
{
"name": "sebastian/lines-of-code",

View File

@ -341,7 +341,7 @@ JIT_WARNING
if(ThreadManager::getInstance()->stopAll() > 0){
$logger->debug("Some threads could not be stopped, performing a force-kill");
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
}while(false);

View File

@ -1427,7 +1427,7 @@ class Server{
private function forceShutdownExit() : void{
$this->forceShutdown();
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
public function forceShutdown() : void{
@ -1495,7 +1495,7 @@ class Server{
}catch(\Throwable $e){
$this->logger->logException($e);
$this->logger->emergency("Crashed while crashing, killing process");
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}
@ -1649,7 +1649,7 @@ class Server{
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
sleep($spacing);
}
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
exit(1);
}

View File

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

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockBurnEvent;
use pocketmine\event\block\BlockSpreadEvent;
@ -58,12 +59,16 @@ class Fire extends BaseFire{
return 1;
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->equals(SupportType::FULL());
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
$down = $this->getSide(Facing::DOWN);
if(SoulFire::canBeSupportedBy($down)){
$world->setBlock($this->position, VanillaBlocks::SOUL_FIRE());
}elseif($down->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
}elseif(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->hasAdjacentFlammableBlocks()){
$world->setBlock($this->position, VanillaBlocks::AIR());
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));

View File

@ -48,12 +48,7 @@ class FrostedIce extends Ice{
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->checkAdjacentBlocks(2)){
$world->useBreakOn($this->position);
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
public function onRandomTick() : void{

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\ShulkerBox as TileShulkerBox;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
@ -110,4 +111,8 @@ class ShulkerBox extends Opaque{
return true;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

View File

@ -53,7 +53,7 @@ class KillCommand extends VanillaCommand{
return true;
}
$player->attack(new EntityDamageEvent($player, EntityDamageEvent::CAUSE_SUICIDE, 1000));
$player->attack(new EntityDamageEvent($player, EntityDamageEvent::CAUSE_SUICIDE, $player->getHealth()));
if($player === $sender){
$sender->sendMessage(KnownTranslationFactory::commands_kill_successful($sender->getName()));
}else{

View File

@ -94,4 +94,4 @@ while(!feof($socket)){
//For simplicity's sake, we don't bother with a graceful shutdown here.
//The parent process would normally forcibly terminate the child process anyway, so we only reach this point if the
//parent process was terminated forcibly and didn't clean up after itself.
Process::kill(Process::pid(), false);
Process::kill(Process::pid());

View File

@ -42,8 +42,8 @@ final class BlockStateData{
public const CURRENT_VERSION =
(1 << 24) | //major
(20 << 16) | //minor
(0 << 8) | //patch
(33); //revision
(10 << 8) | //patch
(32); //revision
public const TAG_NAME = "name";
public const TAG_STATES = "states";

View File

@ -98,7 +98,8 @@ final class BlockStateNames{
public const LEVER_DIRECTION = "lever_direction";
public const LIQUID_DEPTH = "liquid_depth";
public const LIT = "lit";
public const CARDINAL_DIRECTION = "minecraft:cardinal_direction";
public const MC_CARDINAL_DIRECTION = "minecraft:cardinal_direction";
public const MC_FACING_DIRECTION = "minecraft:facing_direction";
public const MOISTURIZED_AMOUNT = "moisturized_amount";
public const MONSTER_EGG_STONE_TYPE = "monster_egg_stone_type";
public const MULTI_FACE_DIRECTION_BITS = "multi_face_direction_bits";

View File

@ -131,10 +131,17 @@ final class BlockStateStringValues{
public const LEVER_DIRECTION_UP_NORTH_SOUTH = "up_north_south";
public const LEVER_DIRECTION_WEST = "west";
public const CARDINAL_DIRECTION_EAST = "east";
public const CARDINAL_DIRECTION_NORTH = "north";
public const CARDINAL_DIRECTION_SOUTH = "south";
public const CARDINAL_DIRECTION_WEST = "west";
public const MC_CARDINAL_DIRECTION_EAST = "east";
public const MC_CARDINAL_DIRECTION_NORTH = "north";
public const MC_CARDINAL_DIRECTION_SOUTH = "south";
public const MC_CARDINAL_DIRECTION_WEST = "west";
public const MC_FACING_DIRECTION_DOWN = "down";
public const MC_FACING_DIRECTION_EAST = "east";
public const MC_FACING_DIRECTION_NORTH = "north";
public const MC_FACING_DIRECTION_SOUTH = "south";
public const MC_FACING_DIRECTION_UP = "up";
public const MC_FACING_DIRECTION_WEST = "west";
public const MONSTER_EGG_STONE_TYPE_CHISELED_STONE_BRICK = "chiseled_stone_brick";
public const MONSTER_EGG_STONE_TYPE_COBBLESTONE = "cobblestone";

View File

@ -98,7 +98,9 @@ final class BlockTypeNames{
public const BLACK_CANDLE = "minecraft:black_candle";
public const BLACK_CANDLE_CAKE = "minecraft:black_candle_cake";
public const BLACK_CARPET = "minecraft:black_carpet";
public const BLACK_CONCRETE = "minecraft:black_concrete";
public const BLACK_GLAZED_TERRACOTTA = "minecraft:black_glazed_terracotta";
public const BLACK_SHULKER_BOX = "minecraft:black_shulker_box";
public const BLACK_WOOL = "minecraft:black_wool";
public const BLACKSTONE = "minecraft:blackstone";
public const BLACKSTONE_DOUBLE_SLAB = "minecraft:blackstone_double_slab";
@ -109,8 +111,10 @@ final class BlockTypeNames{
public const BLUE_CANDLE = "minecraft:blue_candle";
public const BLUE_CANDLE_CAKE = "minecraft:blue_candle_cake";
public const BLUE_CARPET = "minecraft:blue_carpet";
public const BLUE_CONCRETE = "minecraft:blue_concrete";
public const BLUE_GLAZED_TERRACOTTA = "minecraft:blue_glazed_terracotta";
public const BLUE_ICE = "minecraft:blue_ice";
public const BLUE_SHULKER_BOX = "minecraft:blue_shulker_box";
public const BLUE_WOOL = "minecraft:blue_wool";
public const BONE_BLOCK = "minecraft:bone_block";
public const BOOKSHELF = "minecraft:bookshelf";
@ -122,9 +126,11 @@ final class BlockTypeNames{
public const BROWN_CANDLE = "minecraft:brown_candle";
public const BROWN_CANDLE_CAKE = "minecraft:brown_candle_cake";
public const BROWN_CARPET = "minecraft:brown_carpet";
public const BROWN_CONCRETE = "minecraft:brown_concrete";
public const BROWN_GLAZED_TERRACOTTA = "minecraft:brown_glazed_terracotta";
public const BROWN_MUSHROOM = "minecraft:brown_mushroom";
public const BROWN_MUSHROOM_BLOCK = "minecraft:brown_mushroom_block";
public const BROWN_SHULKER_BOX = "minecraft:brown_shulker_box";
public const BROWN_WOOL = "minecraft:brown_wool";
public const BUBBLE_COLUMN = "minecraft:bubble_column";
public const BUBBLE_CORAL = "minecraft:bubble_coral";
@ -188,7 +194,6 @@ final class BlockTypeNames{
public const COLORED_TORCH_RG = "minecraft:colored_torch_rg";
public const COMMAND_BLOCK = "minecraft:command_block";
public const COMPOSTER = "minecraft:composter";
public const CONCRETE = "minecraft:concrete";
public const CONCRETE_POWDER = "minecraft:concrete_powder";
public const CONDUIT = "minecraft:conduit";
public const COPPER_BLOCK = "minecraft:copper_block";
@ -229,7 +234,9 @@ final class BlockTypeNames{
public const CYAN_CANDLE = "minecraft:cyan_candle";
public const CYAN_CANDLE_CAKE = "minecraft:cyan_candle_cake";
public const CYAN_CARPET = "minecraft:cyan_carpet";
public const CYAN_CONCRETE = "minecraft:cyan_concrete";
public const CYAN_GLAZED_TERRACOTTA = "minecraft:cyan_glazed_terracotta";
public const CYAN_SHULKER_BOX = "minecraft:cyan_shulker_box";
public const CYAN_WOOL = "minecraft:cyan_wool";
public const DARK_OAK_BUTTON = "minecraft:dark_oak_button";
public const DARK_OAK_DOOR = "minecraft:dark_oak_door";
@ -455,12 +462,16 @@ final class BlockTypeNames{
public const GRAY_CANDLE = "minecraft:gray_candle";
public const GRAY_CANDLE_CAKE = "minecraft:gray_candle_cake";
public const GRAY_CARPET = "minecraft:gray_carpet";
public const GRAY_CONCRETE = "minecraft:gray_concrete";
public const GRAY_GLAZED_TERRACOTTA = "minecraft:gray_glazed_terracotta";
public const GRAY_SHULKER_BOX = "minecraft:gray_shulker_box";
public const GRAY_WOOL = "minecraft:gray_wool";
public const GREEN_CANDLE = "minecraft:green_candle";
public const GREEN_CANDLE_CAKE = "minecraft:green_candle_cake";
public const GREEN_CARPET = "minecraft:green_carpet";
public const GREEN_CONCRETE = "minecraft:green_concrete";
public const GREEN_GLAZED_TERRACOTTA = "minecraft:green_glazed_terracotta";
public const GREEN_SHULKER_BOX = "minecraft:green_shulker_box";
public const GREEN_WOOL = "minecraft:green_wool";
public const GRINDSTONE = "minecraft:grindstone";
public const HANGING_ROOTS = "minecraft:hanging_roots";
@ -513,18 +524,24 @@ final class BlockTypeNames{
public const LIGHT_BLUE_CANDLE = "minecraft:light_blue_candle";
public const LIGHT_BLUE_CANDLE_CAKE = "minecraft:light_blue_candle_cake";
public const LIGHT_BLUE_CARPET = "minecraft:light_blue_carpet";
public const LIGHT_BLUE_CONCRETE = "minecraft:light_blue_concrete";
public const LIGHT_BLUE_GLAZED_TERRACOTTA = "minecraft:light_blue_glazed_terracotta";
public const LIGHT_BLUE_SHULKER_BOX = "minecraft:light_blue_shulker_box";
public const LIGHT_BLUE_WOOL = "minecraft:light_blue_wool";
public const LIGHT_GRAY_CANDLE = "minecraft:light_gray_candle";
public const LIGHT_GRAY_CANDLE_CAKE = "minecraft:light_gray_candle_cake";
public const LIGHT_GRAY_CARPET = "minecraft:light_gray_carpet";
public const LIGHT_GRAY_CONCRETE = "minecraft:light_gray_concrete";
public const LIGHT_GRAY_SHULKER_BOX = "minecraft:light_gray_shulker_box";
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 LIME_CANDLE = "minecraft:lime_candle";
public const LIME_CANDLE_CAKE = "minecraft:lime_candle_cake";
public const LIME_CARPET = "minecraft:lime_carpet";
public const LIME_CONCRETE = "minecraft:lime_concrete";
public const LIME_GLAZED_TERRACOTTA = "minecraft:lime_glazed_terracotta";
public const LIME_SHULKER_BOX = "minecraft:lime_shulker_box";
public const LIME_WOOL = "minecraft:lime_wool";
public const LIT_BLAST_FURNACE = "minecraft:lit_blast_furnace";
public const LIT_DEEPSLATE_REDSTONE_ORE = "minecraft:lit_deepslate_redstone_ore";
@ -538,7 +555,9 @@ final class BlockTypeNames{
public const MAGENTA_CANDLE = "minecraft:magenta_candle";
public const MAGENTA_CANDLE_CAKE = "minecraft:magenta_candle_cake";
public const MAGENTA_CARPET = "minecraft:magenta_carpet";
public const MAGENTA_CONCRETE = "minecraft:magenta_concrete";
public const MAGENTA_GLAZED_TERRACOTTA = "minecraft:magenta_glazed_terracotta";
public const MAGENTA_SHULKER_BOX = "minecraft:magenta_shulker_box";
public const MAGENTA_WOOL = "minecraft:magenta_wool";
public const MAGMA = "minecraft:magma";
public const MANGROVE_BUTTON = "minecraft:mangrove_button";
@ -600,7 +619,9 @@ final class BlockTypeNames{
public const ORANGE_CANDLE = "minecraft:orange_candle";
public const ORANGE_CANDLE_CAKE = "minecraft:orange_candle_cake";
public const ORANGE_CARPET = "minecraft:orange_carpet";
public const ORANGE_CONCRETE = "minecraft:orange_concrete";
public const ORANGE_GLAZED_TERRACOTTA = "minecraft:orange_glazed_terracotta";
public const ORANGE_SHULKER_BOX = "minecraft:orange_shulker_box";
public const ORANGE_WOOL = "minecraft:orange_wool";
public const OXIDIZED_COPPER = "minecraft:oxidized_copper";
public const OXIDIZED_CUT_COPPER = "minecraft:oxidized_cut_copper";
@ -613,8 +634,10 @@ final class BlockTypeNames{
public const PINK_CANDLE = "minecraft:pink_candle";
public const PINK_CANDLE_CAKE = "minecraft:pink_candle_cake";
public const PINK_CARPET = "minecraft:pink_carpet";
public const PINK_CONCRETE = "minecraft:pink_concrete";
public const PINK_GLAZED_TERRACOTTA = "minecraft:pink_glazed_terracotta";
public const PINK_PETALS = "minecraft:pink_petals";
public const PINK_SHULKER_BOX = "minecraft:pink_shulker_box";
public const PINK_WOOL = "minecraft:pink_wool";
public const PISTON = "minecraft:piston";
public const PISTON_ARM_COLLISION = "minecraft:piston_arm_collision";
@ -657,7 +680,9 @@ final class BlockTypeNames{
public const PURPLE_CANDLE = "minecraft:purple_candle";
public const PURPLE_CANDLE_CAKE = "minecraft:purple_candle_cake";
public const PURPLE_CARPET = "minecraft:purple_carpet";
public const PURPLE_CONCRETE = "minecraft:purple_concrete";
public const PURPLE_GLAZED_TERRACOTTA = "minecraft:purple_glazed_terracotta";
public const PURPLE_SHULKER_BOX = "minecraft:purple_shulker_box";
public const PURPLE_WOOL = "minecraft:purple_wool";
public const PURPUR_BLOCK = "minecraft:purpur_block";
public const PURPUR_STAIRS = "minecraft:purpur_stairs";
@ -672,6 +697,7 @@ final class BlockTypeNames{
public const RED_CANDLE = "minecraft:red_candle";
public const RED_CANDLE_CAKE = "minecraft:red_candle_cake";
public const RED_CARPET = "minecraft:red_carpet";
public const RED_CONCRETE = "minecraft:red_concrete";
public const RED_FLOWER = "minecraft:red_flower";
public const RED_GLAZED_TERRACOTTA = "minecraft:red_glazed_terracotta";
public const RED_MUSHROOM = "minecraft:red_mushroom";
@ -680,6 +706,7 @@ final class BlockTypeNames{
public const RED_NETHER_BRICK_STAIRS = "minecraft:red_nether_brick_stairs";
public const RED_SANDSTONE = "minecraft:red_sandstone";
public const RED_SANDSTONE_STAIRS = "minecraft:red_sandstone_stairs";
public const RED_SHULKER_BOX = "minecraft:red_shulker_box";
public const RED_WOOL = "minecraft:red_wool";
public const REDSTONE_BLOCK = "minecraft:redstone_block";
public const REDSTONE_LAMP = "minecraft:redstone_lamp";
@ -705,7 +732,6 @@ final class BlockTypeNames{
public const SEA_PICKLE = "minecraft:sea_pickle";
public const SEAGRASS = "minecraft:seagrass";
public const SHROOMLIGHT = "minecraft:shroomlight";
public const SHULKER_BOX = "minecraft:shulker_box";
public const SILVER_GLAZED_TERRACOTTA = "minecraft:silver_glazed_terracotta";
public const SKULL = "minecraft:skull";
public const SLIME = "minecraft:slime";
@ -856,7 +882,9 @@ final class BlockTypeNames{
public const WHITE_CANDLE = "minecraft:white_candle";
public const WHITE_CANDLE_CAKE = "minecraft:white_candle_cake";
public const WHITE_CARPET = "minecraft:white_carpet";
public const WHITE_CONCRETE = "minecraft:white_concrete";
public const WHITE_GLAZED_TERRACOTTA = "minecraft:white_glazed_terracotta";
public const WHITE_SHULKER_BOX = "minecraft:white_shulker_box";
public const WHITE_WOOL = "minecraft:white_wool";
public const WITHER_ROSE = "minecraft:wither_rose";
public const WOOD = "minecraft:wood";
@ -867,7 +895,9 @@ final class BlockTypeNames{
public const YELLOW_CANDLE = "minecraft:yellow_candle";
public const YELLOW_CANDLE_CAKE = "minecraft:yellow_candle_cake";
public const YELLOW_CARPET = "minecraft:yellow_carpet";
public const YELLOW_CONCRETE = "minecraft:yellow_concrete";
public const YELLOW_FLOWER = "minecraft:yellow_flower";
public const YELLOW_GLAZED_TERRACOTTA = "minecraft:yellow_glazed_terracotta";
public const YELLOW_SHULKER_BOX = "minecraft:yellow_shulker_box";
public const YELLOW_WOOL = "minecraft:yellow_wool";
}

View File

@ -370,6 +370,46 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
DyeColor::YELLOW() => Ids::YELLOW_CARPET,
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
}));
$this->map(Blocks::DYED_SHULKER_BOX(), fn(DyedShulkerBox $block) => Writer::create(match($color = $block->getColor()){
DyeColor::BLACK() => Ids::BLACK_SHULKER_BOX,
DyeColor::BLUE() => Ids::BLUE_SHULKER_BOX,
DyeColor::BROWN() => Ids::BROWN_SHULKER_BOX,
DyeColor::CYAN() => Ids::CYAN_SHULKER_BOX,
DyeColor::GRAY() => Ids::GRAY_SHULKER_BOX,
DyeColor::GREEN() => Ids::GREEN_SHULKER_BOX,
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_SHULKER_BOX,
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_SHULKER_BOX,
DyeColor::LIME() => Ids::LIME_SHULKER_BOX,
DyeColor::MAGENTA() => Ids::MAGENTA_SHULKER_BOX,
DyeColor::ORANGE() => Ids::ORANGE_SHULKER_BOX,
DyeColor::PINK() => Ids::PINK_SHULKER_BOX,
DyeColor::PURPLE() => Ids::PURPLE_SHULKER_BOX,
DyeColor::RED() => Ids::RED_SHULKER_BOX,
DyeColor::WHITE() => Ids::WHITE_SHULKER_BOX,
DyeColor::YELLOW() => Ids::YELLOW_SHULKER_BOX,
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
}));
$this->map(Blocks::CONCRETE(), fn(Concrete $block) => Writer::create(match($color = $block->getColor()){
DyeColor::BLACK() => Ids::BLACK_CONCRETE,
DyeColor::BLUE() => Ids::BLUE_CONCRETE,
DyeColor::BROWN() => Ids::BROWN_CONCRETE,
DyeColor::CYAN() => Ids::CYAN_CONCRETE,
DyeColor::GRAY() => Ids::GRAY_CONCRETE,
DyeColor::GREEN() => Ids::GREEN_CONCRETE,
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_CONCRETE,
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_CONCRETE,
DyeColor::LIME() => Ids::LIME_CONCRETE,
DyeColor::MAGENTA() => Ids::MAGENTA_CONCRETE,
DyeColor::ORANGE() => Ids::ORANGE_CONCRETE,
DyeColor::PINK() => Ids::PINK_CONCRETE,
DyeColor::PURPLE() => Ids::PURPLE_CONCRETE,
DyeColor::RED() => Ids::RED_CONCRETE,
DyeColor::WHITE() => Ids::WHITE_CONCRETE,
DyeColor::YELLOW() => Ids::YELLOW_CONCRETE,
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
}));
}
private function registerFlatCoralSerializers() : void{
@ -1066,10 +1106,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::CONCRETE(), function(Concrete $block) : Writer{
return Writer::create(Ids::CONCRETE)
->writeColor($block->getColor());
});
$this->map(Blocks::CONCRETE_POWDER(), function(ConcretePowder $block) : Writer{
return Writer::create(Ids::CONCRETE_POWDER)
->writeColor($block->getColor());
@ -1136,10 +1172,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
});
});
$this->map(Blocks::DOUBLE_TALLGRASS(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_GRASS, Writer::create(Ids::DOUBLE_PLANT)));
$this->map(Blocks::DYED_SHULKER_BOX(), function(DyedShulkerBox $block) : Writer{
return Writer::create(Ids::SHULKER_BOX)
->writeColor($block->getColor());
});
$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)

View File

@ -214,12 +214,12 @@ final class BlockStateReader{
* @throws BlockStateDeserializeException
*/
public function readCardinalHorizontalFacing() : int{
return match($raw = $this->readString(BlockStateNames::CARDINAL_DIRECTION)){
StringValues::CARDINAL_DIRECTION_NORTH => Facing::NORTH,
StringValues::CARDINAL_DIRECTION_SOUTH => Facing::SOUTH,
StringValues::CARDINAL_DIRECTION_WEST => Facing::WEST,
StringValues::CARDINAL_DIRECTION_EAST => Facing::EAST,
default => throw $this->badValueException(BlockStateNames::CARDINAL_DIRECTION, $raw)
return match($raw = $this->readString(BlockStateNames::MC_CARDINAL_DIRECTION)){
StringValues::MC_CARDINAL_DIRECTION_NORTH => Facing::NORTH,
StringValues::MC_CARDINAL_DIRECTION_SOUTH => Facing::SOUTH,
StringValues::MC_CARDINAL_DIRECTION_WEST => Facing::WEST,
StringValues::MC_CARDINAL_DIRECTION_EAST => Facing::EAST,
default => throw $this->badValueException(BlockStateNames::MC_CARDINAL_DIRECTION, $raw)
};
}

View File

@ -244,6 +244,48 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
] as $id => $color){
$this->mapSimple($id, fn() => Blocks::CARPET()->setColor($color));
}
foreach([
Ids::BLACK_SHULKER_BOX => DyeColor::BLACK(),
Ids::BLUE_SHULKER_BOX => DyeColor::BLUE(),
Ids::BROWN_SHULKER_BOX => DyeColor::BROWN(),
Ids::CYAN_SHULKER_BOX => DyeColor::CYAN(),
Ids::GRAY_SHULKER_BOX => DyeColor::GRAY(),
Ids::GREEN_SHULKER_BOX => DyeColor::GREEN(),
Ids::LIGHT_BLUE_SHULKER_BOX => DyeColor::LIGHT_BLUE(),
Ids::LIGHT_GRAY_SHULKER_BOX => DyeColor::LIGHT_GRAY(),
Ids::LIME_SHULKER_BOX => DyeColor::LIME(),
Ids::MAGENTA_SHULKER_BOX => DyeColor::MAGENTA(),
Ids::ORANGE_SHULKER_BOX => DyeColor::ORANGE(),
Ids::PINK_SHULKER_BOX => DyeColor::PINK(),
Ids::PURPLE_SHULKER_BOX => DyeColor::PURPLE(),
Ids::RED_SHULKER_BOX => DyeColor::RED(),
Ids::WHITE_SHULKER_BOX => DyeColor::WHITE(),
Ids::YELLOW_SHULKER_BOX => DyeColor::YELLOW(),
] as $id => $color){
$this->mapSimple($id, fn() => Blocks::DYED_SHULKER_BOX()->setColor($color));
}
foreach([
Ids::BLACK_CONCRETE => DyeColor::BLACK(),
Ids::BLUE_CONCRETE => DyeColor::BLUE(),
Ids::BROWN_CONCRETE => DyeColor::BROWN(),
Ids::CYAN_CONCRETE => DyeColor::CYAN(),
Ids::GRAY_CONCRETE => DyeColor::GRAY(),
Ids::GREEN_CONCRETE => DyeColor::GREEN(),
Ids::LIGHT_BLUE_CONCRETE => DyeColor::LIGHT_BLUE(),
Ids::LIGHT_GRAY_CONCRETE => DyeColor::LIGHT_GRAY(),
Ids::LIME_CONCRETE => DyeColor::LIME(),
Ids::MAGENTA_CONCRETE => DyeColor::MAGENTA(),
Ids::ORANGE_CONCRETE => DyeColor::ORANGE(),
Ids::PINK_CONCRETE => DyeColor::PINK(),
Ids::PURPLE_CONCRETE => DyeColor::PURPLE(),
Ids::RED_CONCRETE => DyeColor::RED(),
Ids::WHITE_CONCRETE => DyeColor::WHITE(),
Ids::YELLOW_CONCRETE => DyeColor::YELLOW(),
] as $id => $color){
$this->mapSimple($id, fn() => Blocks::CONCRETE()->setColor($color));
}
}
private function registerFlatCoralDeserializers() : void{
@ -875,10 +917,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
Blocks::GREEN_TORCH()->setFacing($in->readTorchFacing()) :
Blocks::RED_TORCH()->setFacing($in->readTorchFacing());
});
$this->map(Ids::CONCRETE, function(Reader $in) : Block{
return Blocks::CONCRETE()
->setColor($in->readColor());
});
$this->map(Ids::CONCRETE_POWDER, function(Reader $in) : Block{
return Blocks::CONCRETE_POWDER()
->setColor($in->readColor());
@ -1162,7 +1200,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->mapStairs(Ids::PRISMARINE_BRICKS_STAIRS, fn() => Blocks::PRISMARINE_BRICKS_STAIRS());
$this->mapStairs(Ids::PRISMARINE_STAIRS, fn() => Blocks::PRISMARINE_STAIRS());
$this->map(Ids::PUMPKIN, function(Reader $in) : Block{
$in->ignored(StateNames::CARDINAL_DIRECTION); //obsolete
$in->ignored(StateNames::MC_CARDINAL_DIRECTION); //obsolete
return Blocks::PUMPKIN();
});
$this->map(Ids::PUMPKIN_STEM, fn(Reader $in) => Helper::decodeStem(Blocks::PUMPKIN_STEM(), $in));
@ -1285,10 +1323,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
->setCount($in->readBoundedInt(StateNames::CLUSTER_COUNT, 0, 3) + 1)
->setUnderwater(!$in->readBool(StateNames::DEAD_BIT));
});
$this->map(Ids::SHULKER_BOX, function(Reader $in) : Block{
return Blocks::DYED_SHULKER_BOX()
->setColor($in->readColor());
});
$this->map(Ids::SKULL, function(Reader $in) : Block{
return Blocks::MOB_HEAD()
->setFacing($in->readFacingWithoutDown());

View File

@ -170,11 +170,11 @@ final class BlockStateWriter{
* @return $this
*/
public function writeCardinalHorizontalFacing(int $value) : self{
return $this->writeString(BlockStateNames::CARDINAL_DIRECTION, match($value){
Facing::SOUTH => StringValues::CARDINAL_DIRECTION_SOUTH,
Facing::WEST => StringValues::CARDINAL_DIRECTION_WEST,
Facing::NORTH => StringValues::CARDINAL_DIRECTION_NORTH,
Facing::EAST => StringValues::CARDINAL_DIRECTION_EAST,
return $this->writeString(BlockStateNames::MC_CARDINAL_DIRECTION, match($value){
Facing::SOUTH => StringValues::MC_CARDINAL_DIRECTION_SOUTH,
Facing::WEST => StringValues::MC_CARDINAL_DIRECTION_WEST,
Facing::NORTH => StringValues::MC_CARDINAL_DIRECTION_NORTH,
Facing::EAST => StringValues::MC_CARDINAL_DIRECTION_EAST,
default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
});
}

View File

@ -124,6 +124,7 @@ final class ItemTypeNames{
public const COMPARATOR = "minecraft:comparator";
public const COMPASS = "minecraft:compass";
public const COMPOUND = "minecraft:compound";
public const CONCRETE = "minecraft:concrete";
public const COOKED_BEEF = "minecraft:cooked_beef";
public const COOKED_CHICKEN = "minecraft:cooked_chicken";
public const COOKED_COD = "minecraft:cooked_cod";
@ -405,6 +406,7 @@ final class ItemTypeNames{
public const SHEEP_SPAWN_EGG = "minecraft:sheep_spawn_egg";
public const SHELTER_POTTERY_SHERD = "minecraft:shelter_pottery_sherd";
public const SHIELD = "minecraft:shield";
public const SHULKER_BOX = "minecraft:shulker_box";
public const SHULKER_SHELL = "minecraft:shulker_shell";
public const SHULKER_SPAWN_EGG = "minecraft:shulker_spawn_egg";
public const SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:silence_armor_trim_smithing_template";

View File

@ -519,7 +519,12 @@ abstract class Entity{
}
public function attack(EntityDamageEvent $source) : void{
if($this->isFireProof() && ($source->getCause() === EntityDamageEvent::CAUSE_FIRE || $source->getCause() === EntityDamageEvent::CAUSE_FIRE_TICK)){
if($this->isFireProof() && (
$source->getCause() === EntityDamageEvent::CAUSE_FIRE ||
$source->getCause() === EntityDamageEvent::CAUSE_FIRE_TICK ||
$source->getCause() === EntityDamageEvent::CAUSE_LAVA
)
){
$source->cancel();
}
$source->call();
@ -686,8 +691,10 @@ abstract class Entity{
if($fireTicks < 0 || $fireTicks > 0x7fff){
throw new \InvalidArgumentException("Fire ticks must be in range 0 ... " . 0x7fff . ", got $fireTicks");
}
$this->fireTicks = $fireTicks;
$this->networkPropertiesDirty = true;
if(!$this->isFireProof()){
$this->fireTicks = $fireTicks;
$this->networkPropertiesDirty = true;
}
}
public function extinguish() : void{
@ -700,12 +707,13 @@ abstract class Entity{
}
protected function doOnFireTick(int $tickDiff = 1) : bool{
if($this->isFireProof() && $this->fireTicks > 1){
$this->fireTicks = 1;
}else{
$this->fireTicks -= $tickDiff;
if($this->isFireProof() && $this->isOnFire()){
$this->extinguish();
return false;
}
$this->fireTicks -= $tickDiff;
if(($this->fireTicks % 20 === 0) || $tickDiff > 20){
$this->dealFireDamage();
}

View File

@ -484,14 +484,16 @@ abstract class Living extends Entity{
public function damageArmor(float $damage) : void{
$durabilityRemoved = (int) max(floor($damage / 4), 1);
$armor = $this->armorInventory->getContents(true);
foreach($armor as $item){
$armor = $this->armorInventory->getContents();
foreach($armor as $slotId => $item){
if($item instanceof Armor){
$oldItem = clone $item;
$this->damageItem($item, $durabilityRemoved);
if(!$item->equalsExact($oldItem)){
$this->armorInventory->setItem($slotId, $item);
}
}
}
$this->armorInventory->setContents($armor);
}
private function damageItem(Durable $item, int $durabilityRemoved) : void{
@ -502,7 +504,7 @@ abstract class Living extends Entity{
}
public function attack(EntityDamageEvent $source) : void{
if($this->noDamageTicks > 0){
if($this->noDamageTicks > 0 && $source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE){
$source->cancel();
}
@ -515,7 +517,9 @@ abstract class Living extends Entity{
$source->cancel();
}
$this->applyDamageModifiers($source);
if($source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE){
$this->applyDamageModifiers($source);
}
if($source instanceof EntityDamageByEntityEvent && (
$source->getCause() === EntityDamageEvent::CAUSE_BLOCK_EXPLOSION ||
@ -637,9 +641,12 @@ abstract class Living extends Entity{
}
foreach($this->armorInventory->getContents() as $index => $item){
$oldItem = clone $item;
if($item->onTickWorn($this)){
$hasUpdate = true;
$this->armorInventory->setItem($index, $item);
if(!$item->equalsExact($oldItem)){
$this->armorInventory->setItem($index, $item);
}
}
}
}

View File

@ -61,6 +61,7 @@ use const OPENSSL_ALGO_SHA384;
use const STR_PAD_LEFT;
final class JwtUtils{
public const BEDROCK_SIGNING_KEY_CURVE_NAME = "secp384r1";
/**
* @return string[]
@ -203,6 +204,17 @@ final class JwtUtils{
if($signingKeyOpenSSL === false){
throw new JwtException("OpenSSL failed to parse key: " . openssl_error_string());
}
$details = openssl_pkey_get_details($signingKeyOpenSSL);
if($details === false){
throw new JwtException("OpenSSL failed to get details from key: " . openssl_error_string());
}
if(!isset($details['ec']['curve_name'])){
throw new JwtException("Expected an EC key");
}
$curve = $details['ec']['curve_name'];
if($curve !== self::BEDROCK_SIGNING_KEY_CURVE_NAME){
throw new JwtException("Key must belong to curve " . self::BEDROCK_SIGNING_KEY_CURVE_NAME . ", got $curve");
}
return $signingKeyOpenSSL;
}
}

View File

@ -83,6 +83,7 @@ use pocketmine\network\mcpe\protocol\types\AbilitiesLayer;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\command\CommandData;
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
use pocketmine\network\mcpe\protocol\types\command\CommandOverload;
use pocketmine\network\mcpe\protocol\types\command\CommandParameter;
use pocketmine\network\mcpe\protocol\types\command\CommandPermissions;
use pocketmine\network\mcpe\protocol\types\DimensionIds;
@ -985,8 +986,9 @@ class NetworkSession{
0,
$aliasObj,
[
[CommandParameter::standard("args", AvailableCommandsPacket::ARG_TYPE_RAWTEXT, 0, true)]
]
new CommandOverload(chaining: false, parameters: [CommandParameter::standard("args", AvailableCommandsPacket::ARG_TYPE_RAWTEXT, 0, true)])
],
chainedSubCommandData: []
);
$commandData[$command->getLabel()] = $data;

View File

@ -139,6 +139,6 @@ final class StandardEntityEventBroadcaster implements EntityEventBroadcaster{
}
public function onEmote(array $recipients, Human $from, string $emoteId) : void{
$this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, "", "", EmotePacket::FLAG_SERVER));
$this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, "", "", EmotePacket::FLAG_SERVER | EmotePacket::FLAG_MUTE_ANNOUNCEMENT));
}
}

View File

@ -34,7 +34,6 @@ use pocketmine\thread\NonThreadSafeValue;
use function base64_decode;
use function igbinary_serialize;
use function igbinary_unserialize;
use function openssl_error_string;
use function time;
class ProcessLoginTask extends AsyncTask{
@ -164,7 +163,8 @@ class ProcessLoginTask extends AsyncTask{
try{
$signingKeyOpenSSL = JwtUtils::parseDerPublicKey($headerDerKey);
}catch(JwtException $e){
throw new VerifyLoginException("Invalid JWT public key: " . openssl_error_string());
//TODO: we shouldn't be showing this internal information to the client
throw new VerifyLoginException("Invalid JWT public key: " . $e->getMessage(), null, 0, $e);
}
try{
if(!JwtUtils::verify($jwt, $signingKeyOpenSSL)){
@ -204,6 +204,12 @@ class ProcessLoginTask extends AsyncTask{
if($identityPublicKey === false){
throw new VerifyLoginException("Invalid identityPublicKey: base64 error decoding");
}
try{
//verify key format and parameters
JwtUtils::parseDerPublicKey($identityPublicKey);
}catch(JwtException $e){
throw new VerifyLoginException("Invalid identityPublicKey: " . $e->getMessage(), null, 0, $e);
}
$currentPublicKey = $identityPublicKey; //if there are further links, the next link should be signed with this
}
}

View File

@ -33,6 +33,7 @@ use function hex2bin;
use function openssl_digest;
use function openssl_error_string;
use function openssl_pkey_derive;
use function openssl_pkey_get_details;
use function str_pad;
use const STR_PAD_LEFT;
@ -42,7 +43,20 @@ final class EncryptionUtils{
//NOOP
}
private static function validateKey(\OpenSSLAsymmetricKey $key) : void{
$keyDetails = Utils::assumeNotFalse(openssl_pkey_get_details($key));
if(!isset($keyDetails["ec"]["curve_name"])){
throw new \InvalidArgumentException("Key must be an EC key");
}
$curveName = $keyDetails["ec"]["curve_name"];
if($curveName !== JwtUtils::BEDROCK_SIGNING_KEY_CURVE_NAME){
throw new \InvalidArgumentException("Key must belong to the " . JwtUtils::BEDROCK_SIGNING_KEY_CURVE_NAME . " elliptic curve, got $curveName");
}
}
public static function generateSharedSecret(\OpenSSLAsymmetricKey $localPriv, \OpenSSLAsymmetricKey $remotePub) : \GMP{
self::validateKey($localPriv);
self::validateKey($remotePub);
$hexSecret = openssl_pkey_derive($remotePub, $localPriv, 48);
if($hexSecret === false){
throw new \InvalidArgumentException("Failed to derive shared secret: " . openssl_error_string());

View File

@ -70,6 +70,7 @@ final class ItemStackContainerIdTranslator{
ContainerUIIds::MATERIAL_REDUCER_OUTPUT,
ContainerUIIds::SMITHING_TABLE_INPUT,
ContainerUIIds::SMITHING_TABLE_MATERIAL,
ContainerUIIds::SMITHING_TABLE_TEMPLATE,
ContainerUIIds::STONECUTTER_INPUT,
ContainerUIIds::TRADE2_INGREDIENT1,
ContainerUIIds::TRADE2_INGREDIENT2,
@ -84,6 +85,7 @@ final class ItemStackContainerIdTranslator{
ContainerUIIds::FURNACE_FUEL,
ContainerUIIds::FURNACE_INGREDIENT,
ContainerUIIds::FURNACE_RESULT,
ContainerUIIds::HORSE_EQUIP,
ContainerUIIds::LEVEL_ENTITY, //chest
ContainerUIIds::SHULKER_BOX,
ContainerUIIds::SMOKER_INGREDIENT => [$currentWindowId, $slotId],

View File

@ -30,7 +30,7 @@ use const M_SQRT2;
final class ChunkSelector{
/**
* @preturn \Generator|int[]
* @return \Generator|int[]
* @phpstan-return \Generator<int, int, void, void>
*/
public function selectChunks(int $radius, int $centerX, int $centerZ) : \Generator{

View File

@ -1195,10 +1195,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
return !$this->gamemode->equals(GameMode::CREATIVE());
}
public function isFireProof() : bool{
return $this->isCreative();
}
public function getDrops() : array{
if($this->hasFiniteResources()){
return parent::getDrops();
@ -1436,6 +1432,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->entityBaseTick($tickDiff);
Timings::$entityBaseTick->stopTiming();
if($this->isCreative() && $this->fireTicks > 1){
$this->fireTicks = 1;
}
if(!$this->isSpectator() && $this->isAlive()){
Timings::$playerCheckNearEntities->startTiming();
$this->checkNearEntities();

View File

@ -125,7 +125,10 @@ final class Process{
return count(ThreadManager::getInstance()->getAll()) + 2; //MainLogger + Main Thread
}
public static function kill(int $pid, bool $subprocesses) : void{
/**
* @param bool $subprocesses @deprecated
*/
public static function kill(int $pid, bool $subprocesses = false) : void{
$logger = \GlobalLogger::get();
if($logger instanceof MainLogger){
$logger->syncFlushBuffer();

View File

@ -42,7 +42,7 @@ class ServerKiller extends Thread{
});
if(time() - $start >= $this->time){
echo "\nTook too long to stop, server was killed forcefully!\n";
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}

View File

@ -59,7 +59,7 @@ abstract class StringToTParser{
}
/**
* Tries to parse the specified string into an enchantment.
* Tries to parse the specified string into a corresponding instance of T.
* @phpstan-return T|null
*/
public function parse(string $input){

View File

@ -51,11 +51,11 @@ use function time;
class BedrockWorldData extends BaseNbtWorldData{
public const CURRENT_STORAGE_VERSION = 10;
public const CURRENT_STORAGE_NETWORK_VERSION = 589;
public const CURRENT_STORAGE_NETWORK_VERSION = 594;
public const CURRENT_CLIENT_VERSION_TARGET = [
1, //major
20, //minor
0, //patch
10, //patch
1, //revision
0 //is beta
];

View File

@ -27,6 +27,7 @@ use pocketmine\block\Block;
use pocketmine\data\bedrock\BiomeIds;
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\NBT;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
@ -155,7 +156,33 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
$nbt = new LittleEndianNbtSerializer();
$palette = [];
$paletteSize = $bitsPerBlock === 0 ? 1 : $stream->getLInt();
if($bitsPerBlock === 0){
$paletteSize = 1;
/*
* Due to code copy-paste in a public plugin, some PM4 worlds have 0 bpb palettes with a length prefix.
* This is invalid and does not happen in vanilla.
* These palettes were accepted by PM4 despite being invalid, but PM5 considered them corrupt, causing loss
* of data. Since many users were affected by this, a workaround is therefore necessary to allow PM5 to read
* these worlds without data loss.
*
* References:
* - https://github.com/Refaltor77/CustomItemAPI/issues/68
* - https://github.com/pmmp/PocketMine-MP/issues/5911
*/
$offset = $stream->getOffset();
$byte1 = $stream->getByte();
$stream->setOffset($offset); //reset offset
if($byte1 !== NBT::TAG_Compound){ //normally the first byte would be the NBT of the blockstate
$susLength = $stream->getLInt();
if($susLength !== 1){ //make sure the data isn't complete garbage
throw new CorruptedChunkException("CustomItemAPI borked 0 bpb palette should always have a length of 1");
}
$logger->error("Unexpected palette size for 0 bpb palette");
}
}else{
$paletteSize = $stream->getLInt();
}
for($i = 0; $i < $paletteSize; ++$i){
try{
@ -276,6 +303,10 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
$previous = $decoded;
if($nextIndex <= Chunk::MAX_SUBCHUNK_INDEX){ //older versions wrote additional superfluous biome palettes
$result[$nextIndex++] = $decoded;
}elseif($stream->feof()){
//not enough padding biome arrays for the given version - this is non-critical since we discard the excess anyway, but this should be logged
$logger->error("Wrong number of 3D biome palettes for this chunk version: expected $expectedCount, but got " . ($i + 1) . " - this is not a problem, but may indicate a corrupted chunk");
break;
}
}catch(BinaryDataException $e){
throw new CorruptedChunkException("Failed to deserialize biome palette $i: " . $e->getMessage(), 0, $e);