Merge branch 'minor-next' into major-next

This commit is contained in:
Dylan K. Taylor
2025-09-17 01:49:29 +01:00
13 changed files with 140 additions and 54 deletions

View File

@@ -29,6 +29,9 @@ use pocketmine\data\bedrock\block\BlockStateStringValues;
use pocketmine\data\bedrock\block\BlockTypeNames;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\nbt\NbtException;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\convert\BlockStateDictionary;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils;
@@ -78,6 +81,9 @@ function generateBlockPaletteReport(array $states) : BlockPaletteReport{
$name = $stateData->getName();
$result->seenTypes[$name] = $name;
foreach(Utils::stringifyKeys($stateData->getStates()) as $k => $v){
if(!$v instanceof ByteTag && !$v instanceof IntTag && !$v instanceof StringTag){
throw new AssumptionFailedError("Assumed all state tags should be TAG_Byte, TAG_Int or TAG_String, but found $k ($v) on block $name");
}
$result->seenStateValues[$k][$v->getValue()] = $v->getValue();
asort($result->seenStateValues[$k]);
}

View File

@@ -133,3 +133,15 @@ Released 31st August 2025.
## Fixes
- Fixed banners placed in prior versions getting their tiles deleted (due to missing `Type` tags).
# 5.33.2
Released 16th September 2025.
## General
- PHP 8.4 has now been added to the test matrix.
## Fixes
- Fixed PHP 8.4 deprecation notice in `AsyncGeneratorExecutor`.
- Fixed inventory windows breaking if a window is sent while the player has the chat window open (e.g. quickly pressing E followed by / could trigger this).
- Fixed `BlockBreakEvent` being called twice in creative if cancelled.
- Reduced block lag when towering and other situations where the placed block might intersect with the player's AABB. Block lag may still appear on higher latency clients - this is still being worked on.

View File

@@ -52,7 +52,7 @@
"symfony/filesystem": "~7.3.0"
},
"require-dev": {
"phpstan/phpstan": "2.1.17",
"phpstan/phpstan": "2.1.25",
"phpstan/phpstan-phpunit": "^2.0.0",
"phpstan/phpstan-strict-rules": "^2.0.0",
"phpunit/phpunit": "^12.2.1"

78
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": "18849119d6f65f95466fba65546f8877",
"content-hash": "29c0ef75af9772a73a671e153ca912f7",
"packages": [
{
"name": "adhocore/json-comment",
@@ -256,16 +256,16 @@
},
{
"name": "pocketmine/bedrock-protocol",
"version": "41.0.0+bedrock-1.21.100",
"version": "41.0.1+bedrock-1.21.100",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "920ac291fe1b0143b2ebc90b3374ddab0b8531bf"
"reference": "01f54c3e86ddfd3d9354b17a57c7b9a6064f3795"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/920ac291fe1b0143b2ebc90b3374ddab0b8531bf",
"reference": "920ac291fe1b0143b2ebc90b3374ddab0b8531bf",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/01f54c3e86ddfd3d9354b17a57c7b9a6064f3795",
"reference": "01f54c3e86ddfd3d9354b17a57c7b9a6064f3795",
"shasum": ""
},
"require": {
@@ -296,9 +296,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/41.0.0+bedrock-1.21.100"
"source": "https://github.com/pmmp/BedrockProtocol/tree/41.0.1+bedrock-1.21.100"
},
"time": "2025-09-09T20:52:18+00:00"
"time": "2025-09-14T19:29:22+00:00"
},
{
"name": "pocketmine/binaryutils",
@@ -1204,16 +1204,16 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.17",
"version": "2.1.25",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053"
"reference": "4087d28bd252895874e174d65e26b2c202ed893a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053",
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/4087d28bd252895874e174d65e26b2c202ed893a",
"reference": "4087d28bd252895874e174d65e26b2c202ed893a",
"shasum": ""
},
"require": {
@@ -1258,25 +1258,25 @@
"type": "github"
}
],
"time": "2025-05-21T20:55:28+00:00"
"time": "2025-09-12T14:26:42+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
"version": "2.0.6",
"version": "2.0.7",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "6b92469f8a7995e626da3aa487099617b8dfa260"
"reference": "9a9b161baee88a5f5c58d816943cff354ff233dc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6b92469f8a7995e626da3aa487099617b8dfa260",
"reference": "6b92469f8a7995e626da3aa487099617b8dfa260",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/9a9b161baee88a5f5c58d816943cff354ff233dc",
"reference": "9a9b161baee88a5f5c58d816943cff354ff233dc",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"phpstan/phpstan": "^2.0.4"
"phpstan/phpstan": "^2.1.18"
},
"conflict": {
"phpunit/phpunit": "<7.0"
@@ -1309,9 +1309,9 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
"source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.6"
"source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.7"
},
"time": "2025-03-26T12:47:06+00:00"
"time": "2025-07-13T11:31:46+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
@@ -1697,16 +1697,16 @@
},
{
"name": "phpunit/phpunit",
"version": "12.3.10",
"version": "12.3.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "0d401d0df2e3c1703be425ecdc2d04f5c095938d"
"reference": "6a62f2b394e042884e4997ddc8b8db1ce56a0009"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0d401d0df2e3c1703be425ecdc2d04f5c095938d",
"reference": "0d401d0df2e3c1703be425ecdc2d04f5c095938d",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6a62f2b394e042884e4997ddc8b8db1ce56a0009",
"reference": "6a62f2b394e042884e4997ddc8b8db1ce56a0009",
"shasum": ""
},
"require": {
@@ -1725,7 +1725,7 @@
"phpunit/php-invoker": "^6.0.0",
"phpunit/php-text-template": "^5.0.0",
"phpunit/php-timer": "^8.0.0",
"sebastian/cli-parser": "^4.0.0",
"sebastian/cli-parser": "^4.1.0",
"sebastian/comparator": "^7.1.3",
"sebastian/diff": "^7.0.0",
"sebastian/environment": "^8.0.3",
@@ -1774,7 +1774,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.10"
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.11"
},
"funding": [
{
@@ -1798,20 +1798,20 @@
"type": "tidelift"
}
],
"time": "2025-09-11T10:35:19+00:00"
"time": "2025-09-14T06:21:44+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "4.0.0",
"version": "4.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c"
"reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/6d584c727d9114bcdc14c86711cd1cad51778e7c",
"reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/90f41072d220e5c40df6e8635f5dafba2d9d4d04",
"reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04",
"shasum": ""
},
"require": {
@@ -1823,7 +1823,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "4.0-dev"
"dev-main": "4.2-dev"
}
},
"autoload": {
@@ -1847,15 +1847,27 @@
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/4.0.0"
"source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser",
"type": "tidelift"
}
],
"time": "2025-02-07T04:53:50+00:00"
"time": "2025-09-14T09:36:45+00:00"
},
{
"name": "sebastian/comparator",

View File

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

View File

@@ -278,6 +278,10 @@ final class BlockStateUpgrader{
private function applyPropertyFlattened(BlockStateUpgradeSchemaFlattenInfo $flattenInfo, string $oldName, array $states) : array{
$flattenedValue = $states[$flattenInfo->flattenedProperty] ?? null;
$expectedType = $flattenInfo->flattenedPropertyType;
if($expectedType === null){
//TODO: we can't make this non-nullable in a patch release
throw new AssumptionFailedError("We never give this null");
}
if(!$flattenedValue instanceof $expectedType){
//flattened property is not of the expected type, so this transformation is not applicable
return [$oldName, $states];

View File

@@ -67,6 +67,7 @@ use pocketmine\player\InventoryWindow;
use pocketmine\player\Player;
use pocketmine\player\PlayerInventoryWindow;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Binary;
use pocketmine\utils\ObjectSet;
use function array_fill_keys;
use function array_keys;
@@ -448,6 +449,15 @@ class InventoryManager implements InventoryListener{
}
public function onClientRemoveWindow(int $id) : void{
if(Binary::signByte($id) === ContainerIds::NONE){ //TODO: REMOVE signByte() once BedrockProtocol + ext-encoding are implemented
//TODO: HACK! Since 1.21.100 (and probably earlier), the client will send -1 to close windows that it can't
//view for some reason, e.g. if the chat window was already open. This is pretty awkward, since it means
//that we can only assume it refers to the most recently sent window, and if we don't handle it,
//InventoryManager will never get the green light to send subsequent windows, which breaks inventory UIs.
//Fortunately, we already wait for close acks anyway, so the window ID is technically useless...?
$this->session->getLogger()->debug("Client rejected opening of a window, assuming it was $this->lastWindowNetworkId");
$id = $this->lastWindowNetworkId;
}
if($id === $this->lastWindowNetworkId){
if(isset($this->networkIdToWindowMap[$id]) && $id !== $this->pendingCloseWindowId){
$this->remove($id);

View File

@@ -89,6 +89,7 @@ use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
use pocketmine\network\mcpe\protocol\types\inventory\MismatchTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction;
use pocketmine\network\mcpe\protocol\types\inventory\NormalTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\PredictedResult;
use pocketmine\network\mcpe\protocol\types\inventory\ReleaseItemTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\ItemStackRequest;
use pocketmine\network\mcpe\protocol\types\inventory\stackresponse\ItemStackResponse;
@@ -498,11 +499,13 @@ class InGamePacketHandler extends PacketHandler{
$blockPos = $data->getBlockPosition();
$vBlockPos = new Vector3($blockPos->getX(), $blockPos->getY(), $blockPos->getZ());
$this->player->interactBlock($vBlockPos, $face, $clickPos);
//always sync this in case plugins caused a different result than the client expected
//we *could* try to enhance detection of plugin-altered behaviour, but this would require propagating
//more information up the stack. For now I think this is good enough.
//if only the client would tell us what blocks it thinks changed...
$this->syncBlocksNearby($vBlockPos, $face);
if($data->getClientInteractPrediction() === PredictedResult::SUCCESS){
//always sync this in case plugins caused a different result than the client expected
//we *could* try to enhance detection of plugin-altered behaviour, but this would require propagating
//more information up the stack. For now I think this is good enough.
//if only the client would tell us what blocks it thinks changed...
$this->syncBlocksNearby($vBlockPos, $face);
}
return true;
case UseItemTransactionData::ACTION_CLICK_AIR:
if($this->player->isUsingItem()){
@@ -720,7 +723,8 @@ class InGamePacketHandler extends PacketHandler{
case PlayerAction::INTERACT_BLOCK: //TODO: ignored (for now)
break;
case PlayerAction::CREATIVE_PLAYER_DESTROY_BLOCK:
//TODO: do we need to handle this?
//in server auth block breaking, we get PREDICT_DESTROY_BLOCK anyway, so this action is redundant
break;
case PlayerAction::PREDICT_DESTROY_BLOCK:
if(!$this->player->breakBlock($pos)){
$face = self::deserializeFacing($extraData);

View File

@@ -384,6 +384,12 @@ parameters:
count: 3
path: ../../../src/block/Mycelium.php
-
message: '#^Offset 0\|1\|2\|3\|4\|5\|6\|7\|8\|9 might not exist on array\{array\{2, 3\}, array\{5, 4\}, array\{4, 16777221\}, array\{5, 16777220\}, array\{3, 16777218\}, array\{2, 16777219\}\}\.$#'
identifier: offsetAccess.notFound
count: 1
path: ../../../src/block/Rail.php
-
message: '#^Parameter \#1 \$x of method pocketmine\\world\\World\:\:getFullLightAt\(\) expects int, float\|int given\.$#'
identifier: argument.type
@@ -588,6 +594,12 @@ parameters:
count: 1
path: ../../../src/entity/object/FallingBlock.php
-
message: '#^Offset 0\|1\|2\|3\|4\|5 might not exist on array\{3\: 0, 4\: 1, 2\: 2, 5\: 3\}\.$#'
identifier: offsetAccess.notFound
count: 3
path: ../../../src/entity/object/Painting.php
-
message: '#^Parameter \#1 \$x of method pocketmine\\world\\World\:\:getBlockAt\(\) expects int, float\|int given\.$#'
identifier: argument.type
@@ -888,6 +900,12 @@ parameters:
count: 1
path: ../../../src/plugin/PluginDescription.php
-
message: '#^Property pocketmine\\plugin\\PluginDescription\:\:\$srcNamespacePrefix \(string\) does not accept mixed\.$#'
identifier: assign.propertyType
count: 1
path: ../../../src/plugin/PluginDescription.php
-
message: '#^Cannot call method addChild\(\) on pocketmine\\permission\\Permission\|null\.$#'
identifier: method.nonObject
@@ -930,6 +948,12 @@ parameters:
count: 1
path: ../../../src/scheduler/TaskScheduler.php
-
message: '#^Possibly invalid array key type mixed\.$#'
identifier: offsetAccess.invalidOffset
count: 1
path: ../../../src/thread/ThreadManager.php
-
message: '#^Cannot access offset string on mixed\.$#'
identifier: offsetAccess.nonOffsetAccessible

View File

@@ -192,18 +192,6 @@ parameters:
count: 1
path: ../../../src/network/mcpe/cache/CraftingDataCache.php
-
message: '#^Method pocketmine\\network\\mcpe\\compression\\ZlibCompressor\:\:getNetworkId\(\) never returns 1 so it can be removed from the return type\.$#'
identifier: return.unusedType
count: 1
path: ../../../src/network/mcpe/compression/ZlibCompressor.php
-
message: '#^Method pocketmine\\network\\mcpe\\compression\\ZlibCompressor\:\:getNetworkId\(\) never returns 255 so it can be removed from the return type\.$#'
identifier: return.unusedType
count: 1
path: ../../../src/network/mcpe/compression/ZlibCompressor.php
-
message: '#^Parameter \#1 \$states of class pocketmine\\network\\mcpe\\convert\\BlockStateDictionary constructor expects list\<pocketmine\\network\\mcpe\\convert\\BlockStateDictionaryEntry\>, array\<int\<0, max\>, pocketmine\\network\\mcpe\\convert\\BlockStateDictionaryEntry\> given\.$#'
identifier: argument.type

View File

@@ -30,3 +30,26 @@ parameters:
count: 4
path: ../../../src/world/generator/noise/Noise.php
-
message: '#^Parameter \$q00 of static method pocketmine\\world\\generator\\noise\\Noise\:\:bilinearLerp\(\) expects float, float\|null given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/generator/noise/Noise.php
-
message: '#^Parameter \$q01 of static method pocketmine\\world\\generator\\noise\\Noise\:\:bilinearLerp\(\) expects float, float\|null given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/generator/noise/Noise.php
-
message: '#^Parameter \$q10 of static method pocketmine\\world\\generator\\noise\\Noise\:\:bilinearLerp\(\) expects float, float\|null given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/generator/noise/Noise.php
-
message: '#^Parameter \$q11 of static method pocketmine\\world\\generator\\noise\\Noise\:\:bilinearLerp\(\) expects float, float\|null given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/generator/noise/Noise.php

View File

@@ -48,7 +48,7 @@ final class CloningRegistryTraitTest extends TestCase{
public function testGetAllClone() : void{
$list1 = TestCloningRegistry::getAll();
$list2 = TestCloningRegistry::getAll();
foreach(Utils::promoteKeys($list1) as $k => $member){
foreach(Utils::stringifyKeys($list1) as $k => $member){
self::assertNotSame($member, $list2[$k], "VanillaBlocks ought to clone its members");
}
}

View File

@@ -354,6 +354,9 @@ function processStateGroup(string $oldName, array $upgradeTable, BlockStateUpgra
* @param string[] $strings
*/
function findCommonPrefix(array $strings) : string{
if(count($strings) === 0){
return "";
}
sort($strings, SORT_STRING);
$first = $strings[array_key_first($strings)];