From dc07ac33d33cf3a87b49ccf7983a9c0fb44db479 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 20 Oct 2021 19:47:32 +0100 Subject: [PATCH 1/5] protocol: fixed missing field of CraftRecipeAuto --- .../CraftRecipeAutoStackRequestAction.php | 28 ++++++++++- .../CraftRecipeStackRequestAction.php | 21 ++++++++- .../CraftRecipeStackRequestActionTrait.php | 47 ------------------- 3 files changed, 47 insertions(+), 49 deletions(-) delete mode 100644 src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestActionTrait.php diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeAutoStackRequestAction.php b/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeAutoStackRequestAction.php index d5f10ee1f..e146afec0 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeAutoStackRequestAction.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeAutoStackRequestAction.php @@ -23,12 +23,38 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types\inventory\stackrequest; +use pocketmine\network\mcpe\NetworkBinaryStream; + /** * Tells that the current transaction crafted the specified recipe, using the recipe book. This is effectively the same * as the regular crafting result action. */ final class CraftRecipeAutoStackRequestAction extends ItemStackRequestAction{ - use CraftRecipeStackRequestActionTrait; + + /** @var int */ + private $recipeId; + /** @var int */ + private $repetitions; + + final public function __construct(int $recipeId, int $repetitions){ + $this->recipeId = $recipeId; + $this->repetitions = $repetitions; + } + + public function getRecipeId() : int{ return $this->recipeId; } + + public function getRepetitions() : int{ return $this->repetitions; } public static function getTypeId() : int{ return ItemStackRequestActionType::CRAFTING_RECIPE_AUTO; } + + public static function read(NetworkBinaryStream $in) : self{ + $recipeId = $in->readGenericTypeNetworkId(); + $repetitions = $in->getByte(); + return new self($recipeId, $repetitions); + } + + public function write(NetworkBinaryStream $out) : void{ + $out->writeGenericTypeNetworkId($this->recipeId); + $out->putByte($this->repetitions); + } } diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestAction.php b/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestAction.php index 6341aecc5..0a79642de 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestAction.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestAction.php @@ -23,11 +23,30 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types\inventory\stackrequest; +use pocketmine\network\mcpe\NetworkBinaryStream; + /** * Tells that the current transaction crafted the specified recipe. */ final class CraftRecipeStackRequestAction extends ItemStackRequestAction{ - use CraftRecipeStackRequestActionTrait; + + /** @var int */ + private $recipeId; + + final public function __construct(int $recipeId){ + $this->recipeId = $recipeId; + } + + public function getRecipeId() : int{ return $this->recipeId; } public static function getTypeId() : int{ return ItemStackRequestActionType::CRAFTING_RECIPE; } + + public static function read(NetworkBinaryStream $in) : self{ + $recipeId = $in->readGenericTypeNetworkId(); + return new self($recipeId); + } + + public function write(NetworkBinaryStream $out) : void{ + $out->writeGenericTypeNetworkId($this->recipeId); + } } diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestActionTrait.php b/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestActionTrait.php deleted file mode 100644 index 3690562cd..000000000 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/CraftRecipeStackRequestActionTrait.php +++ /dev/null @@ -1,47 +0,0 @@ -recipeId = $recipeId; - } - - public function getRecipeId() : int{ return $this->recipeId; } - - public static function read(NetworkBinaryStream $in) : self{ - $recipeId = $in->readGenericTypeNetworkId(); - return new self($recipeId); - } - - public function write(NetworkBinaryStream $out) : void{ - $out->writeGenericTypeNetworkId($this->recipeId); - } -} From 986b4e0651d665c72ec011542f95b4bd9529c6a8 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 21 Oct 2021 20:32:37 +0100 Subject: [PATCH 2/5] Enforce single-line PhpDoc for properties where possible --- .github/workflows/main.yml | 4 ++-- .php-cs-fixer.php | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 79f39f899..67790cea1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -272,10 +272,10 @@ jobs: - uses: actions/checkout@v2 - name: Setup PHP and tools - uses: shivammathur/setup-php@2.12.0 + uses: shivammathur/setup-php@2.15.0 with: php-version: 8.0 - tools: php-cs-fixer + tools: php-cs-fixer:3.2 - name: Run PHP-CS-Fixer run: php-cs-fixer fix --dry-run --diff diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 373c8fc80..590f6ebd8 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -62,6 +62,11 @@ return (new PhpCsFixer\Config) ], 'sort_algorithm' => 'alpha' ], + 'phpdoc_line_span' => [ + 'property' => 'single', + 'method' => null, + 'const' => null + ], 'phpdoc_trim' => true, 'phpdoc_trim_consecutive_blank_line_separation' => true, 'single_import_per_statement' => true, From f6e53f826b5dcb78f9722603e356c2420cc760e5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 25 Oct 2021 19:52:44 +0100 Subject: [PATCH 3/5] Fixed Anvil/McRegion chunks getting autosaved on first time, even when unchanged setGenerated/setPopulated and friends set hasChanged = true, which causes the world to autosave them the first time around, even though they weren't modified. --- src/pocketmine/level/format/io/region/Anvil.php | 1 + src/pocketmine/level/format/io/region/McRegion.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 6464269cf..bf1e69f0d 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -135,6 +135,7 @@ class Anvil extends McRegion{ $result->setLightPopulated($chunk->getByte("LightPopulated", 0) !== 0); $result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0); $result->setGenerated(); + $result->setChanged(false); return $result; } diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index cde0b06d9..fb39a8e4c 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -201,6 +201,7 @@ class McRegion extends BaseLevelProvider{ $result->setLightPopulated($chunk->getByte("LightPopulated", 0) !== 0); $result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0); $result->setGenerated(true); + $result->setChanged(false); return $result; } From f1cc168d2606b2a1bc52e9d6a7d5f39885566c79 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 29 Oct 2021 00:23:13 +0100 Subject: [PATCH 4/5] phpstan: exclude a couple of files from analysis temporarily close #4472 --- phpstan.neon.dist | 3 +++ 1 file changed, 3 insertions(+) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 0dee95aa2..df2c4a10b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -34,6 +34,9 @@ parameters: analyseAndScan: - build/php - build/preprocessor + analyse: + - src/pocketmine/block/StoneSlab.php #overrides STONE constant + - src/pocketmine/item/Potion.php #overrides WATER constant dynamicConstantNames: - pocketmine\DEBUG - pocketmine\IS_DEVELOPMENT_BUILD From 089e62b44e51dc780306694c4638eeb2e4179b44 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 29 Oct 2021 18:54:00 +0100 Subject: [PATCH 5/5] Entity::spawnTo(): verify that the target player belongs to the same world as the entity this should never be hit in the PM case, but it's an InvalidArgument rather than AssumptionFailedError because plugins can and do call this with bad things. --- src/pocketmine/Player.php | 2 +- src/pocketmine/entity/Entity.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index f08f704ae..9883b52d6 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -563,7 +563,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ } public function spawnTo(Player $player) : void{ - if($this->spawned and $player->spawned and $this->isAlive() and $player->isAlive() and $player->getLevelNonNull() === $this->level and $player->canSee($this) and !$this->isSpectator()){ + if($this->spawned and $player->spawned and $this->isAlive() and $player->isAlive() and $player->canSee($this) and !$this->isSpectator()){ parent::spawnTo($player); } } diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 419a4ee14..c4c017874 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -1950,6 +1950,9 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ } public function spawnTo(Player $player) : void{ + if($player->getLevelNonNull() !== $this->level){ + throw new \InvalidArgumentException("Player is not in the same world"); + } if( !isset($this->hasSpawned[$player->getLoaderId()]) and $this->chunk !== null and