diff --git a/phpstan.neon.dist b/phpstan.neon.dist index c8556a7fd..3880ad102 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,7 +8,7 @@ includes: - tests/phpstan/configs/runtime-type-checks.neon parameters: - level: 4 + level: 5 autoload_files: - tests/phpstan/bootstrap.php - src/pocketmine/PocketMine.php diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 0e012e0cd..6de2b0fb7 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -2247,6 +2247,9 @@ class Server{ $this->crashDump(); } + /** + * @return void + */ public function crashDump(){ while(@ob_end_flush()){} if(!$this->isRunning){ diff --git a/src/pocketmine/block/EnderChest.php b/src/pocketmine/block/EnderChest.php index ea5afb257..1f1f5e6dd 100644 --- a/src/pocketmine/block/EnderChest.php +++ b/src/pocketmine/block/EnderChest.php @@ -84,6 +84,9 @@ class EnderChest extends Chest{ $enderChest = $t; }else{ $enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this)); + if(!($enderChest instanceof TileEnderChest)){ + return true; + } } if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){ diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index a2b3468e9..22d1e79fc 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -463,12 +463,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ /** @var Block[]|null */ protected $blocksAround = null; - /** @var float|null */ - public $lastX = null; - /** @var float|null */ - public $lastY = null; - /** @var float|null */ - public $lastZ = null; + /** @var float */ + public $lastX; + /** @var float */ + public $lastY; + /** @var float */ + public $lastZ; /** @var Vector3 */ protected $motion; diff --git a/src/pocketmine/inventory/PlayerInventory.php b/src/pocketmine/inventory/PlayerInventory.php index 067eccb41..6ffca62df 100644 --- a/src/pocketmine/inventory/PlayerInventory.php +++ b/src/pocketmine/inventory/PlayerInventory.php @@ -66,19 +66,23 @@ class PlayerInventory extends BaseInventory{ * @return bool if the equipment change was successful, false if not. */ public function equipItem(int $hotbarSlot) : bool{ + $holder = $this->getHolder(); if(!$this->isHotbarSlot($hotbarSlot)){ - $this->sendContents($this->getHolder()); + if($holder instanceof Player){ + $this->sendContents($holder); + } return false; } - $ev = new PlayerItemHeldEvent($this->getHolder(), $this->getItem($hotbarSlot), $hotbarSlot); - $ev->call(); + if($holder instanceof Player){ + $ev = new PlayerItemHeldEvent($holder, $this->getItem($hotbarSlot), $hotbarSlot); + $ev->call(); - if($ev->isCancelled()){ - $this->sendHeldItem($this->getHolder()); - return false; + if($ev->isCancelled()){ + $this->sendHeldItem($holder); + return false; + } } - $this->setHeldItemIndex($hotbarSlot, false); return true; diff --git a/src/pocketmine/lang/BaseLang.php b/src/pocketmine/lang/BaseLang.php index aece04221..0ec3a68f2 100644 --- a/src/pocketmine/lang/BaseLang.php +++ b/src/pocketmine/lang/BaseLang.php @@ -115,9 +115,9 @@ class BaseLang{ } /** - * @param string $str - * @param string[] $params - * @param string|null $onlyPrefix + * @param string $str + * @param (float|int|string)[] $params + * @param string|null $onlyPrefix * * @return string */ diff --git a/src/pocketmine/lang/TranslationContainer.php b/src/pocketmine/lang/TranslationContainer.php index aa9bf3d01..69461b281 100644 --- a/src/pocketmine/lang/TranslationContainer.php +++ b/src/pocketmine/lang/TranslationContainer.php @@ -31,8 +31,8 @@ class TranslationContainer extends TextContainer{ protected $params = []; /** - * @param string $text - * @param string[] $params + * @param string $text + * @param (float|int|string)[] $params */ public function __construct(string $text, array $params = []){ parent::__construct($text); diff --git a/src/pocketmine/level/Location.php b/src/pocketmine/level/Location.php index d29f8b26c..435e82575 100644 --- a/src/pocketmine/level/Location.php +++ b/src/pocketmine/level/Location.php @@ -33,12 +33,12 @@ class Location extends Position{ public $pitch; /** - * @param int $x - * @param int $y - * @param int $z - * @param float $yaw - * @param float $pitch - * @param Level $level + * @param float|int $x + * @param float|int $y + * @param float|int $z + * @param float $yaw + * @param float $pitch + * @param Level $level */ public function __construct($x = 0, $y = 0, $z = 0, $yaw = 0.0, $pitch = 0.0, Level $level = null){ $this->yaw = $yaw; diff --git a/src/pocketmine/level/Position.php b/src/pocketmine/level/Position.php index 608c412c5..cb8ea44b7 100644 --- a/src/pocketmine/level/Position.php +++ b/src/pocketmine/level/Position.php @@ -33,10 +33,10 @@ class Position extends Vector3{ public $level = null; /** - * @param int $x - * @param int $y - * @param int $z - * @param Level $level + * @param float|int $x + * @param float|int $y + * @param float|int $z + * @param Level $level */ public function __construct($x = 0, $y = 0, $z = 0, Level $level = null){ parent::__construct($x, $y, $z); diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index 10229f49c..a6aef3060 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -26,6 +26,7 @@ namespace pocketmine\level\format\io\leveldb; use pocketmine\level\format\Chunk; use pocketmine\level\format\io\BaseLevelProvider; use pocketmine\level\format\io\ChunkUtils; +use pocketmine\level\format\io\exception\CorruptedChunkException; use pocketmine\level\format\io\exception\UnsupportedChunkFormatException; use pocketmine\level\format\SubChunk; use pocketmine\level\generator\Flat; @@ -414,24 +415,27 @@ class LevelDB extends BaseLevelProvider{ /** @var CompoundTag[] $entities */ $entities = []; if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and $entityData !== ""){ - $entities = $nbt->read($entityData, true); - if(!is_array($entities)){ - $entities = [$entities]; - } - } - - /** @var CompoundTag $entityNBT */ - foreach($entities as $entityNBT){ - if($entityNBT->hasTag("id", IntTag::class)){ - $entityNBT->setInt("id", $entityNBT->getInt("id") & 0xff); //remove type flags - TODO: use these instead of removing them) + $entityTags = $nbt->read($entityData, true); + foreach((is_array($entityTags) ? $entityTags : [$entityTags]) as $entityTag){ + if(!($entityTag instanceof CompoundTag)){ + throw new CorruptedChunkException("Entity root tag should be TAG_Compound"); + } + if($entityTag->hasTag("id", IntTag::class)){ + $entityTag->setInt("id", $entityTag->getInt("id") & 0xff); //remove type flags - TODO: use these instead of removing them) + } + $entities[] = $entityTag; } } + /** @var CompoundTag[] $tiles */ $tiles = []; if(($tileData = $this->db->get($index . self::TAG_BLOCK_ENTITY)) !== false and $tileData !== ""){ - $tiles = $nbt->read($tileData, true); - if(!is_array($tiles)){ - $tiles = [$tiles]; + $tileTags = $nbt->read($tileData, true); + foreach((is_array($tileTags) ? $tileTags : [$tileTags]) as $tileTag){ + if(!($tileTag instanceof CompoundTag)){ + throw new CorruptedChunkException("Tile root tag should be TAG_Compound"); + } + $tiles[] = $tileTag; } } diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 12b1cc965..d602fd8a2 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -51,7 +51,7 @@ class Anvil extends McRegion{ $subChunks = []; foreach($chunk->getSubChunks() as $y => $subChunk){ - if($subChunk->isEmpty()){ + if(!($subChunk instanceof SubChunk) or $subChunk->isEmpty()){ continue; } @@ -122,8 +122,8 @@ class Anvil extends McRegion{ $chunk->getInt("xPos"), $chunk->getInt("zPos"), $subChunks, - $chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [], - $chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [], + $chunk->hasTag("Entities", ListTag::class) ? self::getCompoundList("Entities", $chunk->getListTag("Entities")) : [], + $chunk->hasTag("TileEntities", ListTag::class) ? self::getCompoundList("TileEntities", $chunk->getListTag("TileEntities")) : [], $biomeIds, $chunk->getIntArray("HeightMap", []) ); diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index 9f2871635..51cad2438 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -194,8 +194,8 @@ class McRegion extends BaseLevelProvider{ $chunk->getInt("xPos"), $chunk->getInt("zPos"), $subChunks, - $chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [], - $chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [], + $chunk->hasTag("Entities", ListTag::class) ? self::getCompoundList("Entities", $chunk->getListTag("Entities")) : [], + $chunk->hasTag("TileEntities", ListTag::class) ? self::getCompoundList("TileEntities", $chunk->getListTag("TileEntities")) : [], $biomeIds, $heightMap ); @@ -205,6 +205,31 @@ class McRegion extends BaseLevelProvider{ return $result; } + /** + * @param string $context + * @param ListTag $list + * + * @return CompoundTag[] + * @throws CorruptedChunkException + */ + protected static function getCompoundList(string $context, ListTag $list) : array{ + if($list->count() === 0){ //empty lists might have wrong types, we don't care + return []; + } + if($list->getTagType() !== NBT::TAG_Compound){ + throw new CorruptedChunkException("Expected TAG_List for '$context'"); + } + $result = []; + foreach($list as $tag){ + if(!($tag instanceof CompoundTag)){ + //this should never happen, but it's still possible due to lack of native type safety + throw new CorruptedChunkException("Expected TAG_List for '$context'"); + } + $result[] = $tag; + } + return $result; + } + public static function getProviderName() : string{ return "mcregion"; } diff --git a/src/pocketmine/network/CompressBatchedTask.php b/src/pocketmine/network/CompressBatchedTask.php index 86b784d31..d0f6757c2 100644 --- a/src/pocketmine/network/CompressBatchedTask.php +++ b/src/pocketmine/network/CompressBatchedTask.php @@ -35,7 +35,7 @@ class CompressBatchedTask extends AsyncTask{ /** * @param BatchPacket $batch - * @param string[] $targets + * @param Player[] $targets */ public function __construct(BatchPacket $batch, array $targets){ $this->data = $batch->payload;