diff --git a/src/MemoryDump.php b/src/MemoryDump.php index 5a9c274cb..bd1e0fc9a 100644 --- a/src/MemoryDump.php +++ b/src/MemoryDump.php @@ -253,12 +253,12 @@ final class MemoryDump{ } /** - * @param object[] $objects reference parameter - * @param int[] $refCounts reference parameter + * @param object[]|true[] $objects reference parameter + * @param int[] $refCounts reference parameter * - * @phpstan-param array $objects + * @phpstan-param array $objects * @phpstan-param array $refCounts - * @phpstan-param-out array $objects + * @phpstan-param-out array $objects * @phpstan-param-out array $refCounts */ private static function continueDump(mixed $from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : mixed{ diff --git a/src/block/Anvil.php b/src/block/Anvil.php index 0a1a47070..2c48f9a7c 100644 --- a/src/block/Anvil.php +++ b/src/block/Anvil.php @@ -70,9 +70,6 @@ class Anvil extends Transparent implements Fallable{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)]; } diff --git a/src/block/Bamboo.php b/src/block/Bamboo.php index 9f605bca6..fd64e10ef 100644 --- a/src/block/Bamboo.php +++ b/src/block/Bamboo.php @@ -87,9 +87,6 @@ class Bamboo extends Transparent{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ //this places the BB at the northwest corner, not the center $inset = 1 - (($this->thick ? 3 : 2) / 16); diff --git a/src/block/BaseBanner.php b/src/block/BaseBanner.php index 6b9e493d1..b56323453 100644 --- a/src/block/BaseBanner.php +++ b/src/block/BaseBanner.php @@ -30,7 +30,6 @@ use pocketmine\block\utils\SupportType; use pocketmine\item\Banner as ItemBanner; use pocketmine\item\Item; use pocketmine\item\VanillaItems; -use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\world\BlockTransaction; @@ -97,9 +96,6 @@ abstract class BaseBanner extends Transparent{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return []; } diff --git a/src/block/BaseSign.php b/src/block/BaseSign.php index 5a905f8b8..0f5d77d58 100644 --- a/src/block/BaseSign.php +++ b/src/block/BaseSign.php @@ -34,7 +34,6 @@ use pocketmine\event\block\SignChangeEvent; use pocketmine\item\Dye; use pocketmine\item\Item; use pocketmine\item\ItemTypeIds; -use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\utils\TextFormat; @@ -95,9 +94,6 @@ abstract class BaseSign extends Transparent{ return 16; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return []; } diff --git a/src/block/Bed.php b/src/block/Bed.php index 8efbdfe01..133c4a9cc 100644 --- a/src/block/Bed.php +++ b/src/block/Bed.php @@ -76,9 +76,6 @@ class Bed extends Transparent{ } } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)]; } diff --git a/src/block/Block.php b/src/block/Block.php index 89fe39265..36e08fc0b 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -75,7 +75,10 @@ class Block{ protected BlockTypeInfo $typeInfo; protected Position $position; - /** @var AxisAlignedBB[]|null */ + /** + * @var AxisAlignedBB[]|null + * @phpstan-var list|null + */ protected ?array $collisionBoxes = null; private int $requiredBlockItemStateDataBits; @@ -907,6 +910,7 @@ class Block{ * - anti-cheat checks in plugins * * @return AxisAlignedBB[] + * @phpstan-return list */ final public function getCollisionBoxes() : array{ if($this->collisionBoxes === null){ @@ -931,6 +935,7 @@ class Block{ /** * @return AxisAlignedBB[] + * @phpstan-return list */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()]; diff --git a/src/block/BlockBreakInfo.php b/src/block/BlockBreakInfo.php index b49cb6f13..8cfa425dc 100644 --- a/src/block/BlockBreakInfo.php +++ b/src/block/BlockBreakInfo.php @@ -95,7 +95,7 @@ class BlockBreakInfo{ * Returns whether this block can be instantly broken. */ public function breaksInstantly() : bool{ - return $this->hardness == 0.0; + return $this->hardness === 0.0; } /** diff --git a/src/block/Cactus.php b/src/block/Cactus.php index 6f2b04c8a..67b15b946 100644 --- a/src/block/Cactus.php +++ b/src/block/Cactus.php @@ -43,9 +43,6 @@ class Cactus extends Transparent{ return true; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ $shrinkSize = 1 / 16; return [AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize)]; diff --git a/src/block/Cake.php b/src/block/Cake.php index 073fc62ac..e8c6dc93e 100644 --- a/src/block/Cake.php +++ b/src/block/Cake.php @@ -40,9 +40,6 @@ class Cake extends BaseCake{ $w->boundedIntAuto(0, self::MAX_BITES, $this->bites); } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [ AxisAlignedBB::one() diff --git a/src/block/CakeWithCandle.php b/src/block/CakeWithCandle.php index 380d080c5..546843d6c 100644 --- a/src/block/CakeWithCandle.php +++ b/src/block/CakeWithCandle.php @@ -36,9 +36,6 @@ class CakeWithCandle extends BaseCake{ onInteract as onInteractCandle; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [ AxisAlignedBB::one() diff --git a/src/block/Carpet.php b/src/block/Carpet.php index 1ee7240c5..2d8e7ea47 100644 --- a/src/block/Carpet.php +++ b/src/block/Carpet.php @@ -36,9 +36,6 @@ class Carpet extends Flowable{ return true; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 15 / 16)]; } diff --git a/src/block/Chest.php b/src/block/Chest.php index dca21576a..7d2650007 100644 --- a/src/block/Chest.php +++ b/src/block/Chest.php @@ -36,9 +36,6 @@ use pocketmine\player\Player; class Chest extends Transparent{ use FacesOppositePlacingPlayerTrait; - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ //these are slightly bigger than in PC return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)]; diff --git a/src/block/CocoaBlock.php b/src/block/CocoaBlock.php index 6d8ce1adc..83e1de34b 100644 --- a/src/block/CocoaBlock.php +++ b/src/block/CocoaBlock.php @@ -50,9 +50,6 @@ class CocoaBlock extends Flowable{ $w->boundedIntAuto(0, self::MAX_AGE, $this->age); } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [ AxisAlignedBB::one() diff --git a/src/block/DaylightSensor.php b/src/block/DaylightSensor.php index 4141a2b7e..5720af529 100644 --- a/src/block/DaylightSensor.php +++ b/src/block/DaylightSensor.php @@ -62,9 +62,6 @@ class DaylightSensor extends Transparent{ return 300; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 10 / 16)]; } diff --git a/src/block/Door.php b/src/block/Door.php index 82ddaab51..fa88267e1 100644 --- a/src/block/Door.php +++ b/src/block/Door.php @@ -95,9 +95,6 @@ class Door extends Transparent{ return false; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ //TODO: doors are 0.1825 blocks thick, instead of 0.1875 like JE (https://bugs.mojang.com/browse/MCPE-19214) return [AxisAlignedBB::one()->trim($this->open ? Facing::rotateY($this->facing, !$this->hingeRight) : $this->facing, 327 / 400)]; diff --git a/src/block/EnchantingTable.php b/src/block/EnchantingTable.php index 6a6c936b2..53573d064 100644 --- a/src/block/EnchantingTable.php +++ b/src/block/EnchantingTable.php @@ -33,9 +33,6 @@ use pocketmine\player\Player; class EnchantingTable extends Transparent{ - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 0.25)]; } diff --git a/src/block/EndPortalFrame.php b/src/block/EndPortalFrame.php index 612cf3723..ed5b77433 100644 --- a/src/block/EndPortalFrame.php +++ b/src/block/EndPortalFrame.php @@ -50,9 +50,6 @@ class EndPortalFrame extends Opaque{ return 1; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 3 / 16)]; } diff --git a/src/block/EndRod.php b/src/block/EndRod.php index f0b28c26d..a6770f370 100644 --- a/src/block/EndRod.php +++ b/src/block/EndRod.php @@ -52,9 +52,6 @@ class EndRod extends Flowable{ return 14; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ $myAxis = Facing::axis($this->facing); diff --git a/src/block/EnderChest.php b/src/block/EnderChest.php index 9004f7c79..6a8cf108c 100644 --- a/src/block/EnderChest.php +++ b/src/block/EnderChest.php @@ -40,9 +40,6 @@ class EnderChest extends Transparent{ return 7; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ //these are slightly bigger than in PC return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)]; diff --git a/src/block/Farmland.php b/src/block/Farmland.php index b7a2500a8..83bc34561 100644 --- a/src/block/Farmland.php +++ b/src/block/Farmland.php @@ -94,9 +94,6 @@ class Farmland extends Transparent{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)]; } diff --git a/src/block/Fence.php b/src/block/Fence.php index 30caaa4cf..52256d9f0 100644 --- a/src/block/Fence.php +++ b/src/block/Fence.php @@ -54,13 +54,9 @@ class Fence extends Transparent{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ $inset = 0.5 - $this->getThickness() / 2; - /** @var AxisAlignedBB[] $bbs */ $bbs = []; $connectWest = isset($this->connections[Facing::WEST]); diff --git a/src/block/FenceGate.php b/src/block/FenceGate.php index 735456449..2bbfdf892 100644 --- a/src/block/FenceGate.php +++ b/src/block/FenceGate.php @@ -64,9 +64,6 @@ class FenceGate extends Transparent{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return $this->open ? [] : [AxisAlignedBB::one()->extend(Facing::UP, 0.5)->squash(Facing::axis($this->facing), 6 / 16)]; } diff --git a/src/block/Flowable.php b/src/block/Flowable.php index 0328bcd74..355c9caea 100644 --- a/src/block/Flowable.php +++ b/src/block/Flowable.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\block\utils\SupportType; -use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; /** @@ -46,9 +45,6 @@ abstract class Flowable extends Transparent{ parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock); } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return []; } diff --git a/src/block/FlowerPot.php b/src/block/FlowerPot.php index fb3e78d82..79fb73b12 100644 --- a/src/block/FlowerPot.php +++ b/src/block/FlowerPot.php @@ -83,9 +83,6 @@ class FlowerPot extends Flowable{ return $block->hasTypeTag(BlockTypeTags::POTTABLE_PLANTS); } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->contract(3 / 16, 0, 3 / 16)->trim(Facing::UP, 5 / 8)]; } diff --git a/src/block/GlowLichen.php b/src/block/GlowLichen.php index d30e25395..a44c4d035 100644 --- a/src/block/GlowLichen.php +++ b/src/block/GlowLichen.php @@ -28,7 +28,6 @@ use pocketmine\block\utils\MultiAnySupportTrait; use pocketmine\block\utils\SupportType; use pocketmine\item\Fertilizer; use pocketmine\item\Item; -use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; @@ -47,9 +46,6 @@ class GlowLichen extends Transparent{ return false; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return []; } diff --git a/src/block/GrassPath.php b/src/block/GrassPath.php index 5b11bd374..ea56e4b95 100644 --- a/src/block/GrassPath.php +++ b/src/block/GrassPath.php @@ -29,9 +29,6 @@ use pocketmine\math\Facing; class GrassPath extends Transparent{ - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)]; } diff --git a/src/block/Ladder.php b/src/block/Ladder.php index 58f133f6e..09c0b8f6b 100644 --- a/src/block/Ladder.php +++ b/src/block/Ladder.php @@ -58,9 +58,6 @@ class Ladder extends Transparent{ return true; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim($this->facing, 13 / 16)]; } diff --git a/src/block/Lantern.php b/src/block/Lantern.php index e9cbcc3fe..302e69fd7 100644 --- a/src/block/Lantern.php +++ b/src/block/Lantern.php @@ -59,9 +59,6 @@ class Lantern extends Transparent{ return $this->lightLevel; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [ AxisAlignedBB::one() diff --git a/src/block/Liquid.php b/src/block/Liquid.php index a37019d65..813d76904 100644 --- a/src/block/Liquid.php +++ b/src/block/Liquid.php @@ -30,7 +30,6 @@ use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\entity\Entity; use pocketmine\event\block\BlockSpreadEvent; use pocketmine\item\Item; -use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\utils\Utils; @@ -89,9 +88,6 @@ abstract class Liquid extends Transparent{ return false; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return []; } diff --git a/src/block/MobHead.php b/src/block/MobHead.php index f4e945841..41e816c55 100644 --- a/src/block/MobHead.php +++ b/src/block/MobHead.php @@ -104,9 +104,6 @@ class MobHead extends Flowable{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ $collisionBox = AxisAlignedBB::one() ->contract(0.25, 0, 0.25) diff --git a/src/block/NetherPortal.php b/src/block/NetherPortal.php index 6a45fb7a0..1b199c603 100644 --- a/src/block/NetherPortal.php +++ b/src/block/NetherPortal.php @@ -28,7 +28,6 @@ use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\entity\Entity; use pocketmine\item\Item; use pocketmine\math\Axis; -use pocketmine\math\AxisAlignedBB; class NetherPortal extends Transparent{ @@ -62,9 +61,6 @@ class NetherPortal extends Transparent{ return false; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return []; } diff --git a/src/block/RedstoneComparator.php b/src/block/RedstoneComparator.php index ee63a77a9..40e1ef510 100644 --- a/src/block/RedstoneComparator.php +++ b/src/block/RedstoneComparator.php @@ -79,9 +79,6 @@ class RedstoneComparator extends Flowable{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)]; } diff --git a/src/block/RedstoneRepeater.php b/src/block/RedstoneRepeater.php index 7e6e73da8..bf9d0c5da 100644 --- a/src/block/RedstoneRepeater.php +++ b/src/block/RedstoneRepeater.php @@ -62,9 +62,6 @@ class RedstoneRepeater extends Flowable{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)]; } diff --git a/src/block/SeaPickle.php b/src/block/SeaPickle.php index 627af9bac..34f5c3e9e 100644 --- a/src/block/SeaPickle.php +++ b/src/block/SeaPickle.php @@ -26,7 +26,6 @@ namespace pocketmine\block; use pocketmine\block\utils\SupportType; use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\item\Item; -use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\world\BlockTransaction; @@ -70,9 +69,6 @@ class SeaPickle extends Transparent{ return $this->underwater ? ($this->count + 1) * 3 : 0; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return []; } diff --git a/src/block/Slab.php b/src/block/Slab.php index 6000bec39..2bbb7528c 100644 --- a/src/block/Slab.php +++ b/src/block/Slab.php @@ -93,9 +93,6 @@ class Slab extends Transparent{ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ if($this->slabType === SlabType::DOUBLE){ return [AxisAlignedBB::one()]; diff --git a/src/block/SnowLayer.php b/src/block/SnowLayer.php index cca8424a9..8549f0b31 100644 --- a/src/block/SnowLayer.php +++ b/src/block/SnowLayer.php @@ -65,9 +65,6 @@ class SnowLayer extends Flowable implements Fallable{ return $this->layers < self::MAX_LAYERS; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ //TODO: this zero-height BB is intended to stay in lockstep with a MCPE bug return [AxisAlignedBB::one()->trim(Facing::UP, $this->layers >= 4 ? 0.5 : 1)]; diff --git a/src/block/SoulSand.php b/src/block/SoulSand.php index 2c6453b6c..e1285d095 100644 --- a/src/block/SoulSand.php +++ b/src/block/SoulSand.php @@ -28,9 +28,6 @@ use pocketmine\math\Facing; class SoulSand extends Opaque{ - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 8)]; } diff --git a/src/block/Thin.php b/src/block/Thin.php index dde2d7d84..82010697a 100644 --- a/src/block/Thin.php +++ b/src/block/Thin.php @@ -56,7 +56,6 @@ class Thin extends Transparent{ protected function recalculateCollisionBoxes() : array{ $inset = 7 / 16; - /** @var AxisAlignedBB[] $bbs */ $bbs = []; if(isset($this->connections[Facing::WEST]) || isset($this->connections[Facing::EAST])){ diff --git a/src/block/Trapdoor.php b/src/block/Trapdoor.php index 20b6af2ab..a903e1b5e 100644 --- a/src/block/Trapdoor.php +++ b/src/block/Trapdoor.php @@ -62,9 +62,6 @@ class Trapdoor extends Transparent{ return $this; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->trim($this->open ? $this->facing : ($this->top ? Facing::DOWN : Facing::UP), 13 / 16)]; } diff --git a/src/block/WaterLily.php b/src/block/WaterLily.php index 5dfb0d74a..b04b1baed 100644 --- a/src/block/WaterLily.php +++ b/src/block/WaterLily.php @@ -33,9 +33,6 @@ class WaterLily extends Flowable{ canBePlacedAt as supportedWhenPlacedAt; } - /** - * @return AxisAlignedBB[] - */ protected function recalculateCollisionBoxes() : array{ return [AxisAlignedBB::one()->contract(1 / 16, 0, 1 / 16)->trim(Facing::UP, 63 / 64)]; } diff --git a/src/block/utils/CandleTrait.php b/src/block/utils/CandleTrait.php index c9da97ee0..0cbd13044 100644 --- a/src/block/utils/CandleTrait.php +++ b/src/block/utils/CandleTrait.php @@ -43,7 +43,10 @@ trait CandleTrait{ return $this->lit ? 3 : 0; } - /** @see Block::onInteract() */ + /** + * @param Item[] &$returnedItems + * @see Block::onInteract() + */ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE || $item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){ if($this->lit){ diff --git a/src/block/utils/CopperTrait.php b/src/block/utils/CopperTrait.php index 5ad8aa82d..2ed06b798 100644 --- a/src/block/utils/CopperTrait.php +++ b/src/block/utils/CopperTrait.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace pocketmine\block\utils; +use pocketmine\block\Block; use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\item\Axe; use pocketmine\item\Item; @@ -58,6 +59,10 @@ trait CopperTrait{ return $this; } + /** + * @param Item[] &$returnedItems + * @see Block::onInteract() + */ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ if(!$this->waxed && $item->getTypeId() === ItemTypeIds::HONEYCOMB){ $this->waxed = true; diff --git a/src/command/Command.php b/src/command/Command.php index dbd32e1e8..99b0451c0 100644 --- a/src/command/Command.php +++ b/src/command/Command.php @@ -33,6 +33,7 @@ use pocketmine\permission\PermissionManager; use pocketmine\Server; use pocketmine\utils\BroadcastLoggerForwarder; use pocketmine\utils\TextFormat; +use function array_values; use function explode; use function implode; use function str_replace; @@ -80,6 +81,7 @@ abstract class Command{ /** * @param string[] $args + * @phpstan-param list $args * * @return mixed * @throws CommandException @@ -213,6 +215,7 @@ abstract class Command{ * @phpstan-param list $aliases */ public function setAliases(array $aliases) : void{ + $aliases = array_values($aliases); //because plugins can and will pass crap $this->aliases = $aliases; if(!$this->isRegistered()){ $this->activeAliases = $aliases; diff --git a/src/command/FormattedCommandAlias.php b/src/command/FormattedCommandAlias.php index 5086672f6..b47363397 100644 --- a/src/command/FormattedCommandAlias.php +++ b/src/command/FormattedCommandAlias.php @@ -121,6 +121,7 @@ class FormattedCommandAlias extends Command{ /** * @param string[] $args + * @phpstan-param list $args */ private function buildCommand(string $formatString, array $args) : ?string{ $index = 0; diff --git a/src/command/SimpleCommandMap.php b/src/command/SimpleCommandMap.php index e0d8e6565..9f5441746 100644 --- a/src/command/SimpleCommandMap.php +++ b/src/command/SimpleCommandMap.php @@ -73,6 +73,7 @@ use pocketmine\timings\Timings; use pocketmine\utils\TextFormat; use pocketmine\utils\Utils; use function array_shift; +use function array_values; use function count; use function implode; use function str_contains; @@ -163,7 +164,7 @@ class SimpleCommandMap implements CommandMap{ unset($aliases[$index]); } } - $command->setAliases($aliases); + $command->setAliases(array_values($aliases)); if(!$registered){ $command->setLabel($fallbackPrefix . ":" . $label); diff --git a/src/command/defaults/TimingsCommand.php b/src/command/defaults/TimingsCommand.php index ec26f3efe..08a8b82aa 100644 --- a/src/command/defaults/TimingsCommand.php +++ b/src/command/defaults/TimingsCommand.php @@ -46,6 +46,8 @@ use function fwrite; use function http_build_query; use function implode; use function is_array; +use function is_int; +use function is_string; use function json_decode; use function mkdir; use function strtolower; @@ -178,7 +180,7 @@ class TimingsCommand extends VanillaCommand{ return; } $response = json_decode($result->getBody(), true); - if(is_array($response) && isset($response["id"])){ + if(is_array($response) && isset($response["id"]) && (is_int($response["id"]) || is_string($response["id"]))){ Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead( "https://" . $host . "/?id=" . $response["id"])); }else{ diff --git a/src/entity/Attribute.php b/src/entity/Attribute.php index 829e3d26c..3e9b7d7c2 100644 --- a/src/entity/Attribute.php +++ b/src/entity/Attribute.php @@ -76,7 +76,7 @@ class Attribute{ throw new \InvalidArgumentException("Minimum $minValue is greater than the maximum $max"); } - if($this->minValue != $minValue){ + if($this->minValue !== $minValue){ $this->desynchronized = true; $this->minValue = $minValue; } @@ -95,7 +95,7 @@ class Attribute{ throw new \InvalidArgumentException("Maximum $maxValue is less than the minimum $min"); } - if($this->maxValue != $maxValue){ + if($this->maxValue !== $maxValue){ $this->desynchronized = true; $this->maxValue = $maxValue; } @@ -140,7 +140,7 @@ class Attribute{ $value = min(max($value, $this->getMinValue()), $this->getMaxValue()); } - if($this->currentValue != $value){ + if($this->currentValue !== $value){ $this->desynchronized = true; $this->currentValue = $value; }elseif($forceSend){ diff --git a/src/entity/Entity.php b/src/entity/Entity.php index 3c9d79ae9..d5d4dbea6 100644 --- a/src/entity/Entity.php +++ b/src/entity/Entity.php @@ -72,6 +72,7 @@ use function assert; use function cos; use function count; use function deg2rad; +use function floatval; use function floor; use function fmod; use function get_class; @@ -591,7 +592,7 @@ abstract class Entity{ * Sets the health of the Entity. This won't send any update to the players */ public function setHealth(float $amount) : void{ - if($amount == $this->health){ + if($amount === $this->health){ return; } @@ -760,8 +761,8 @@ abstract class Entity{ $diffMotion = $this->motion->subtractVector($this->lastMotion)->lengthSquared(); - $still = $this->motion->lengthSquared() == 0.0; - $wasStill = $this->lastMotion->lengthSquared() == 0.0; + $still = $this->motion->lengthSquared() === 0.0; + $wasStill = $this->lastMotion->lengthSquared() === 0.0; if($wasStill !== $still){ //TODO: hack for client-side AI interference: prevent client sided movement when motion is 0 $this->setNoClientPredictions($still); @@ -1004,7 +1005,7 @@ abstract class Entity{ abs($this->motion->z) <= self::MOTION_THRESHOLD ? 0 : null ); - if($this->motion->x != 0 || $this->motion->y != 0 || $this->motion->z != 0){ + if(floatval($this->motion->x) !== 0.0 || floatval($this->motion->y) !== 0.0 || floatval($this->motion->z) !== 0.0){ $this->move($this->motion->x, $this->motion->y, $this->motion->z); } @@ -1058,9 +1059,9 @@ abstract class Entity{ public function hasMovementUpdate() : bool{ return ( $this->forceMovementUpdate || - $this->motion->x != 0 || - $this->motion->y != 0 || - $this->motion->z != 0 || + floatval($this->motion->x) !== 0.0 || + floatval($this->motion->y) !== 0.0 || + floatval($this->motion->z) !== 0.0 || !$this->onGround ); } @@ -1163,7 +1164,7 @@ abstract class Entity{ $moveBB->offset(0, $dy, 0); - $fallingFlag = ($this->onGround || ($dy != $wantedY && $wantedY < 0)); + $fallingFlag = ($this->onGround || ($dy !== $wantedY && $wantedY < 0)); foreach($list as $bb){ $dx = $bb->calculateXOffset($moveBB, $dx); @@ -1177,7 +1178,7 @@ abstract class Entity{ $moveBB->offset(0, 0, $dz); - if($this->stepHeight > 0 && $fallingFlag && ($wantedX != $dx || $wantedZ != $dz)){ + if($this->stepHeight > 0 && $fallingFlag && ($wantedX !== $dx || $wantedZ !== $dz)){ $cx = $dx; $cy = $dy; $cz = $dz; @@ -1242,9 +1243,9 @@ abstract class Entity{ $postFallVerticalVelocity = $this->updateFallState($dy, $this->onGround); $this->motion = $this->motion->withComponents( - $wantedX != $dx ? 0 : null, - $postFallVerticalVelocity ?? ($wantedY != $dy ? 0 : null), - $wantedZ != $dz ? 0 : null + $wantedX !== $dx ? 0 : null, + $postFallVerticalVelocity ?? ($wantedY !== $dy ? 0 : null), + $wantedZ !== $dz ? 0 : null ); //TODO: vehicle collision events (first we need to spawn them!) @@ -1253,10 +1254,10 @@ abstract class Entity{ } protected function checkGroundState(float $wantedX, float $wantedY, float $wantedZ, float $dx, float $dy, float $dz) : void{ - $this->isCollidedVertically = $wantedY != $dy; - $this->isCollidedHorizontally = ($wantedX != $dx || $wantedZ != $dz); + $this->isCollidedVertically = $wantedY !== $dy; + $this->isCollidedHorizontally = ($wantedX !== $dx || $wantedZ !== $dz); $this->isCollided = ($this->isCollidedHorizontally || $this->isCollidedVertically); - $this->onGround = ($wantedY != $dy && $wantedY < 0); + $this->onGround = ($wantedY !== $dy && $wantedY < 0); } /** diff --git a/src/entity/Location.php b/src/entity/Location.php index 990108ac4..d9c101882 100644 --- a/src/entity/Location.php +++ b/src/entity/Location.php @@ -66,7 +66,7 @@ class Location extends Position{ public function equals(Vector3 $v) : bool{ if($v instanceof Location){ - return parent::equals($v) && $v->yaw == $this->yaw && $v->pitch == $this->pitch; + return parent::equals($v) && $v->yaw === $this->yaw && $v->pitch === $this->pitch; } return parent::equals($v); } diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 98460bef3..511d0dece 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -118,7 +118,6 @@ use pocketmine\world\Position; use pocketmine\world\World; use pocketmine\YmlServerProperties; use function array_map; -use function array_values; use function base64_encode; use function bin2hex; use function count; @@ -164,7 +163,10 @@ class NetworkSession{ private ?EncryptionContext $cipher = null; - /** @var string[] */ + /** + * @var string[] + * @phpstan-var list + */ private array $sendBuffer = []; /** * @var PromiseResolver[] @@ -544,6 +546,7 @@ class NetworkSession{ * @phpstan-return Promise */ public function sendDataPacketWithReceipt(ClientboundPacket $packet, bool $immediate = false) : Promise{ + /** @phpstan-var PromiseResolver $resolver */ $resolver = new PromiseResolver(); if(!$this->sendDataPacketInternal($packet, $immediate, $resolver)){ @@ -1106,7 +1109,7 @@ class NetworkSession{ //work around a client bug which makes the original name not show when aliases are used $aliases[] = $lname; } - $aliasObj = new CommandEnum(ucfirst($command->getLabel()) . "Aliases", array_values($aliases)); + $aliasObj = new CommandEnum(ucfirst($command->getLabel()) . "Aliases", $aliases); } $description = $command->getDescription(); diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 88b4ba1a0..dba16e1e6 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -416,7 +416,7 @@ class InGamePacketHandler extends PacketHandler{ $droppedCount = null; foreach($data->getActions() as $networkInventoryAction){ - if($networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_WORLD && $networkInventoryAction->inventorySlot == NetworkInventoryAction::ACTION_MAGIC_SLOT_DROP_ITEM){ + if($networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_WORLD && $networkInventoryAction->inventorySlot === NetworkInventoryAction::ACTION_MAGIC_SLOT_DROP_ITEM){ $droppedCount = $networkInventoryAction->newItem->getItemStack()->getCount(); if($droppedCount <= 0){ throw new PacketHandlingException("Expected positive count for dropped item"); @@ -578,7 +578,7 @@ class InGamePacketHandler extends PacketHandler{ private function handleReleaseItemTransaction(ReleaseItemTransactionData $data) : bool{ $this->player->selectHotbarSlot($data->getHotbarSlot()); - if($data->getActionType() == ReleaseItemTransactionData::ACTION_RELEASE){ + if($data->getActionType() === ReleaseItemTransactionData::ACTION_RELEASE){ $this->player->releaseHeldItem(); return true; } diff --git a/src/plugin/PluginDescription.php b/src/plugin/PluginDescription.php index 35ae2ba32..89ac19e05 100644 --- a/src/plugin/PluginDescription.php +++ b/src/plugin/PluginDescription.php @@ -84,11 +84,20 @@ class PluginDescription{ * @phpstan-var array> */ private array $extensions = []; - /** @var string[] */ + /** + * @var string[] + * @phpstan-var list + */ private array $depend = []; - /** @var string[] */ + /** + * @var string[] + * @phpstan-var list + */ private array $softDepend = []; - /** @var string[] */ + /** + * @var string[] + * @phpstan-var list + */ private array $loadBefore = []; private string $version; /** @@ -173,7 +182,7 @@ class PluginDescription{ } if(isset($plugin[self::KEY_DEPEND])){ - $this->depend = (array) $plugin[self::KEY_DEPEND]; + $this->depend = array_values((array) $plugin[self::KEY_DEPEND]); } if(isset($plugin[self::KEY_EXTENSIONS])){ $extensions = (array) $plugin[self::KEY_EXTENSIONS]; @@ -183,13 +192,13 @@ class PluginDescription{ $k = $v; $v = "*"; } - $this->extensions[(string) $k] = array_map('strval', is_array($v) ? $v : [$v]); + $this->extensions[(string) $k] = array_values(array_map('strval', is_array($v) ? $v : [$v])); } } - $this->softDepend = (array) ($plugin[self::KEY_SOFTDEPEND] ?? $this->softDepend); + $this->softDepend = array_values((array) ($plugin[self::KEY_SOFTDEPEND] ?? $this->softDepend)); - $this->loadBefore = (array) ($plugin[self::KEY_LOADBEFORE] ?? $this->loadBefore); + $this->loadBefore = array_values((array) ($plugin[self::KEY_LOADBEFORE] ?? $this->loadBefore)); $this->website = (string) ($plugin[self::KEY_WEBSITE] ?? $this->website); @@ -210,7 +219,7 @@ class PluginDescription{ $this->authors = []; if(isset($plugin[self::KEY_AUTHOR])){ if(is_array($plugin[self::KEY_AUTHOR])){ - $this->authors = $plugin[self::KEY_AUTHOR]; + $this->authors = array_values($plugin[self::KEY_AUTHOR]); }else{ $this->authors[] = $plugin[self::KEY_AUTHOR]; } @@ -284,6 +293,7 @@ class PluginDescription{ /** * @return string[] + * @phpstan-return list */ public function getDepend() : array{ return $this->depend; @@ -295,6 +305,7 @@ class PluginDescription{ /** * @return string[] + * @phpstan-return list */ public function getLoadBefore() : array{ return $this->loadBefore; @@ -324,6 +335,7 @@ class PluginDescription{ /** * @return string[] + * @phpstan-return list */ public function getSoftDepend() : array{ return $this->softDepend; diff --git a/src/plugin/PluginLoadTriage.php b/src/plugin/PluginLoadTriage.php index 77d102668..fcf32751e 100644 --- a/src/plugin/PluginLoadTriage.php +++ b/src/plugin/PluginLoadTriage.php @@ -31,12 +31,12 @@ final class PluginLoadTriage{ public array $plugins = []; /** * @var string[][] - * @phpstan-var array> + * @phpstan-var array> */ public array $dependencies = []; /** * @var string[][] - * @phpstan-var array> + * @phpstan-var array> */ public array $softDependencies = []; } diff --git a/src/plugin/PluginManager.php b/src/plugin/PluginManager.php index da085230a..1a74b64e7 100644 --- a/src/plugin/PluginManager.php +++ b/src/plugin/PluginManager.php @@ -327,12 +327,12 @@ class PluginManager{ * @param string[][] $dependencyLists * @param Plugin[] $loadedPlugins * - * @phpstan-param array> $dependencyLists - * @phpstan-param-out array> $dependencyLists + * @phpstan-param array> $dependencyLists + * @phpstan-param-out array> $dependencyLists */ private function checkDepsForTriage(string $pluginName, string $dependencyType, array &$dependencyLists, array $loadedPlugins, PluginLoadTriage $triage) : void{ if(isset($dependencyLists[$pluginName])){ - foreach($dependencyLists[$pluginName] as $key => $dependency){ + foreach(Utils::promoteKeys($dependencyLists[$pluginName]) as $key => $dependency){ if(isset($loadedPlugins[$dependency]) || $this->getPlugin($dependency) instanceof Plugin){ $this->server->getLogger()->debug("Successfully resolved $dependencyType dependency \"$dependency\" for plugin \"$pluginName\""); unset($dependencyLists[$pluginName][$key]); @@ -399,7 +399,7 @@ class PluginManager{ //check for skippable soft dependencies first, in case the dependents could resolve hard dependencies foreach(Utils::stringifyKeys($triage->plugins) as $name => $file){ if(isset($triage->softDependencies[$name]) && !isset($triage->dependencies[$name])){ - foreach($triage->softDependencies[$name] as $k => $dependency){ + foreach(Utils::promoteKeys($triage->softDependencies[$name]) as $k => $dependency){ if($this->getPlugin($dependency) === null && !array_key_exists($dependency, $triage->plugins)){ $this->server->getLogger()->debug("Skipping resolution of missing soft dependency \"$dependency\" for plugin \"$name\""); unset($triage->softDependencies[$name][$k]); @@ -416,7 +416,7 @@ class PluginManager{ if(isset($triage->dependencies[$name])){ $unknownDependencies = []; - foreach($triage->dependencies[$name] as $k => $dependency){ + foreach($triage->dependencies[$name] as $dependency){ if($this->getPlugin($dependency) === null && !array_key_exists($dependency, $triage->plugins)){ //assume that the plugin is never going to be loaded //by this point all soft dependencies have been ignored if they were able to be, so diff --git a/src/utils/Config.php b/src/utils/Config.php index cabc8fe16..7b6da6389 100644 --- a/src/utils/Config.php +++ b/src/utils/Config.php @@ -72,7 +72,7 @@ class Config{ /** * @var mixed[] - * @phpstan-var array + * @phpstan-var array */ private array $config = []; @@ -450,7 +450,7 @@ class Config{ /** * @return mixed[] - * @phpstan-return list|array + * @phpstan-return list|array */ public function getAll(bool $keys = false) : array{ return ($keys ? array_keys($this->config) : $this->config); @@ -458,7 +458,6 @@ class Config{ /** * @param mixed[] $defaults - * @phpstan-param array $defaults */ public function setDefaults(array $defaults) : void{ $this->fillDefaults($defaults, $this->config); @@ -467,13 +466,11 @@ class Config{ /** * @param mixed[] $default * @param mixed[] $data reference parameter - * @phpstan-param array $default - * @phpstan-param array $data - * @phpstan-param-out array $data + * @phpstan-param-out array $data */ private function fillDefaults(array $default, array &$data) : int{ $changed = 0; - foreach(Utils::stringifyKeys($default) as $k => $v){ + foreach(Utils::promoteKeys($default) as $k => $v){ if(is_array($v)){ if(!isset($data[$k]) || !is_array($data[$k])){ $data[$k] = []; @@ -509,8 +506,8 @@ class Config{ } /** - * @param string[] $entries - * @phpstan-param list $entries + * @param string[]|int[] $entries + * @phpstan-param list $entries */ public static function writeList(array $entries) : string{ return implode("\n", $entries); @@ -518,11 +515,11 @@ class Config{ /** * @param string[]|int[]|float[]|bool[] $config - * @phpstan-param array $config + * @phpstan-param array $config */ public static function writeProperties(array $config) : string{ $content = "#Properties Config file\r\n#" . date("D M j H:i:s T Y") . "\r\n"; - foreach(Utils::stringifyKeys($config) as $k => $v){ + foreach(Utils::promoteKeys($config) as $k => $v){ if(is_bool($v)){ $v = $v ? "on" : "off"; } @@ -534,7 +531,7 @@ class Config{ /** * @return string[]|int[]|float[]|bool[] - * @phpstan-return array + * @phpstan-return array */ public static function parseProperties(string $content) : array{ $result = []; @@ -560,7 +557,7 @@ class Config{ }; break; } - $result[(string) $k] = $v; + $result[$k] = $v; } } diff --git a/src/utils/Git.php b/src/utils/Git.php index 041d795a1..2b9e242bc 100644 --- a/src/utils/Git.php +++ b/src/utils/Git.php @@ -39,7 +39,7 @@ final class Git{ * @param bool $dirty reference parameter, set to whether the repo has local changes */ public static function getRepositoryState(string $dir, bool &$dirty) : ?string{ - if(Process::execute("git -C \"$dir\" rev-parse HEAD", $out) === 0 && $out !== false && strlen($out = trim($out)) === 40){ + if(Process::execute("git -C \"$dir\" rev-parse HEAD", $out) === 0 && strlen($out = trim($out)) === 40){ if(Process::execute("git -C \"$dir\" diff --quiet") === 1 || Process::execute("git -C \"$dir\" diff --cached --quiet") === 1){ //Locally-modified $dirty = true; } diff --git a/src/utils/Internet.php b/src/utils/Internet.php index 07b3c7a33..1811ce51e 100644 --- a/src/utils/Internet.php +++ b/src/utils/Internet.php @@ -100,7 +100,7 @@ class Internet{ } $ip = self::getURL("http://ifconfig.me/ip"); - if($ip !== null && ($addr = trim($ip->getBody())) != ""){ + if($ip !== null && ($addr = trim($ip->getBody())) !== ""){ return self::$ip = $addr; } @@ -157,22 +157,21 @@ class Internet{ * POSTs data to an URL * NOTE: This is a blocking operation and can take a significant amount of time. It is inadvisable to use this method on the main thread. * - * @phpstan-template TErrorVar of mixed - * * @param string[]|string $args * @param string[] $extraHeaders * @param string|null $err reference parameter, will be set to the output of curl_error(). Use this to retrieve errors that occurred during the operation. * @phpstan-param string|array $args * @phpstan-param list $extraHeaders - * @phpstan-param TErrorVar $err - * @phpstan-param-out TErrorVar|string $err + * @phpstan-param-out string|null $err */ public static function postURL(string $page, array|string $args, int $timeout = 10, array $extraHeaders = [], &$err = null) : ?InternetRequestResult{ try{ - return self::simpleCurl($page, $timeout, $extraHeaders, [ + $result = self::simpleCurl($page, $timeout, $extraHeaders, [ CURLOPT_POST => 1, CURLOPT_POSTFIELDS => $args ]); + $err = null; + return $result; }catch(InternetException $ex){ $err = $ex->getMessage(); return null; diff --git a/src/utils/Process.php b/src/utils/Process.php index 1370ab27c..90149870a 100644 --- a/src/utils/Process.php +++ b/src/utils/Process.php @@ -174,8 +174,17 @@ final class Process{ return -1; } - $stdout = stream_get_contents($pipes[1]); - $stderr = stream_get_contents($pipes[2]); + $out = stream_get_contents($pipes[1]); + if($out === false){ + throw new AssumptionFailedError("Presume this can't happen for proc_open ... ???"); + } + $stdout = $out; + + $err = stream_get_contents($pipes[2]); + if($err === false){ + throw new AssumptionFailedError("Presume this can't happen for proc_open ... ???"); + } + $stderr = $err; foreach($pipes as $p){ fclose($p); diff --git a/src/utils/ReversePriorityQueue.php b/src/utils/ReversePriorityQueue.php index 53fd0f08a..03f1aea8d 100644 --- a/src/utils/ReversePriorityQueue.php +++ b/src/utils/ReversePriorityQueue.php @@ -24,7 +24,7 @@ declare(strict_types=1); namespace pocketmine\utils; /** - * @phpstan-template TPriority + * @phpstan-template TPriority of numeric * @phpstan-template TValue * @phpstan-extends \SplPriorityQueue */ diff --git a/src/utils/SignalHandler.php b/src/utils/SignalHandler.php index 82ae02da6..75d38ff97 100644 --- a/src/utils/SignalHandler.php +++ b/src/utils/SignalHandler.php @@ -36,14 +36,12 @@ use const SIGTERM; final class SignalHandler{ /** @phpstan-var (\Closure(int) : void)|null */ - private ?\Closure $interruptCallback; + private ?\Closure $interruptCallback = null; /** * @phpstan-param \Closure() : void $interruptCallback */ public function __construct(\Closure $interruptCallback){ - $this->interruptCallback = $interruptCallback; - if(function_exists('sapi_windows_set_ctrl_handler')){ sapi_windows_set_ctrl_handler($this->interruptCallback = function(int $signo) use ($interruptCallback) : void{ if($signo === PHP_WINDOWS_EVENT_CTRL_C || $signo === PHP_WINDOWS_EVENT_CTRL_BREAK){ diff --git a/src/utils/Timezone.php b/src/utils/Timezone.php index 7f1dcf0e4..6723b12eb 100644 --- a/src/utils/Timezone.php +++ b/src/utils/Timezone.php @@ -134,7 +134,7 @@ abstract class Timezone{ $offset = $matches[2]; - if($offset == ""){ + if($offset === ""){ return "UTC"; } @@ -156,7 +156,7 @@ abstract class Timezone{ $offset = trim(exec('date +%:z')); - if($offset == "+00:00"){ + if($offset === "+00:00"){ return "UTC"; } @@ -195,7 +195,7 @@ abstract class Timezone{ $offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second']; //After date_parse is done, put the sign back - if($negative_offset == true){ + if($negative_offset){ $offset = -abs($offset); } @@ -204,7 +204,7 @@ abstract class Timezone{ //That's been a bug in PHP since 2008! foreach(timezone_abbreviations_list() as $zones){ foreach($zones as $timezone){ - if($timezone['timezone_id'] !== null && $timezone['offset'] == $offset){ + if($timezone['timezone_id'] !== null && $timezone['offset'] === $offset){ return $timezone['timezone_id']; } } diff --git a/src/utils/Utils.php b/src/utils/Utils.php index 9317aff3c..cc33e60e0 100644 --- a/src/utils/Utils.php +++ b/src/utils/Utils.php @@ -220,7 +220,7 @@ final class Utils{ $mac = implode("\n", $mac); if(preg_match_all("#Physical Address[. ]{1,}: ([0-9A-F\\-]{17})#", $mac, $matches) > 0){ foreach($matches[1] as $i => $v){ - if($v == "00-00-00-00-00-00"){ + if($v === "00-00-00-00-00-00"){ unset($matches[1][$i]); } } @@ -234,7 +234,7 @@ final class Utils{ $mac = implode("\n", $mac); if(preg_match_all("#HWaddr[ \t]{1,}([0-9a-f:]{17})#", $mac, $matches) > 0){ foreach($matches[1] as $i => $v){ - if($v == "00:00:00:00:00:00"){ + if($v === "00:00:00:00:00:00"){ unset($matches[1][$i]); } } diff --git a/src/world/World.php b/src/world/World.php index 9551b8cbe..979e0aa54 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -1364,7 +1364,7 @@ class World implements ChunkManager{ * TODO: phpstan can't infer these types yet :( * @phpstan-var array $blockLight * @phpstan-var array $skyLight - * @phpstan-var array $heightMap + * @phpstan-var non-empty-list $heightMap */ if($this->unloaded || ($chunk = $this->getChunk($chunkX, $chunkZ)) === null || $chunk->isLightPopulated() === true){ return; @@ -1562,6 +1562,7 @@ class World implements ChunkManager{ * Larger AABBs (>= 2 blocks on any axis) are not accounted for. * * @return AxisAlignedBB[] + * @phpstan-return list */ private function getBlockCollisionBoxesForCell(int $x, int $y, int $z) : array{ $block = $this->getBlockAt($x, $y, $z); @@ -2021,7 +2022,6 @@ class World implements ChunkManager{ * @phpstan-return list */ public function dropExperience(Vector3 $pos, int $amount) : array{ - /** @var ExperienceOrb[] $orbs */ $orbs = []; foreach(ExperienceOrb::splitIntoOrbSizes($amount) as $split){ @@ -3064,6 +3064,7 @@ class World implements ChunkManager{ * @phpstan-return Promise */ public function requestSafeSpawn(?Vector3 $spawn = null) : Promise{ + /** @phpstan-var PromiseResolver $resolver */ $resolver = new PromiseResolver(); $spawn ??= $this->getSpawnLocation(); /* @@ -3235,6 +3236,7 @@ class World implements ChunkManager{ private function enqueuePopulationRequest(int $chunkX, int $chunkZ, ?ChunkLoader $associatedChunkLoader) : Promise{ $chunkHash = World::chunkHash($chunkX, $chunkZ); $this->addChunkHashToPopulationRequestQueue($chunkHash); + /** @phpstan-var PromiseResolver $resolver */ $resolver = $this->chunkPopulationRequestMap[$chunkHash] = new PromiseResolver(); if($associatedChunkLoader === null){ $temporaryLoader = new class implements ChunkLoader{}; diff --git a/src/world/format/Chunk.php b/src/world/format/Chunk.php index e4c877dc9..9ea5d3f8e 100644 --- a/src/world/format/Chunk.php +++ b/src/world/format/Chunk.php @@ -57,7 +57,10 @@ class Chunk{ */ protected \SplFixedArray $subChunks; - /** @var Tile[] */ + /** + * @var Tile[] + * @phpstan-var array + */ protected array $tiles = []; protected HeightArray $heightMap; @@ -210,6 +213,7 @@ class Chunk{ /** * @return Tile[] + * @phpstan-return array */ public function getTiles() : array{ return $this->tiles; @@ -237,6 +241,7 @@ class Chunk{ /** * @return int[] + * @phpstan-return non-empty-list */ public function getHeightMapArray() : array{ return $this->heightMap->getValues(); @@ -244,6 +249,7 @@ class Chunk{ /** * @param int[] $values + * @phpstan-param non-empty-list $values */ public function setHeightMapArray(array $values) : void{ $this->heightMap = new HeightArray($values); diff --git a/src/world/format/HeightArray.php b/src/world/format/HeightArray.php index 27f9cecb7..03094c3c8 100644 --- a/src/world/format/HeightArray.php +++ b/src/world/format/HeightArray.php @@ -36,7 +36,7 @@ final class HeightArray{ /** * @param int[] $values ZZZZXXXX key bit order - * @phpstan-param list $values + * @phpstan-param non-empty-list $values */ public function __construct(array $values){ if(count($values) !== 256){ @@ -66,7 +66,7 @@ final class HeightArray{ /** * @return int[] ZZZZXXXX key bit order - * @phpstan-return list + * @phpstan-return non-empty-list */ public function getValues() : array{ return $this->array->toArray(); diff --git a/src/world/format/io/FastChunkSerializer.php b/src/world/format/io/FastChunkSerializer.php index 6e18f27ac..35a8ff42f 100644 --- a/src/world/format/io/FastChunkSerializer.php +++ b/src/world/format/io/FastChunkSerializer.php @@ -112,7 +112,6 @@ final class FastChunkSerializer{ $y = Binary::signByte($stream->getByte()); $airBlockId = $stream->getInt(); - /** @var PalettedBlockArray[] $layers */ $layers = []; for($i = 0, $layerCount = $stream->getByte(); $i < $layerCount; ++$i){ $layers[] = self::deserializePalettedArray($stream); diff --git a/src/world/format/io/region/RegionWorldProvider.php b/src/world/format/io/region/RegionWorldProvider.php index 75fcfd083..0ab70300e 100644 --- a/src/world/format/io/region/RegionWorldProvider.php +++ b/src/world/format/io/region/RegionWorldProvider.php @@ -93,10 +93,12 @@ abstract class RegionWorldProvider extends BaseWorldProvider{ } /** - * @param int $regionX reference parameter - * @param int $regionZ reference parameter + * @param int|null $regionX reference parameter + * @param int|null $regionZ reference parameter * @phpstan-param-out int $regionX * @phpstan-param-out int $regionZ + * + * TODO: make this private */ public static function getRegionIndex(int $chunkX, int $chunkZ, &$regionX, &$regionZ) : void{ $regionX = $chunkX >> 5; @@ -154,6 +156,8 @@ abstract class RegionWorldProvider extends BaseWorldProvider{ /** * @return CompoundTag[] + * @phpstan-return list + * * @throws CorruptedChunkException */ protected static function getCompoundList(string $context, ListTag $list) : array{ diff --git a/src/world/light/LightPopulationTask.php b/src/world/light/LightPopulationTask.php index 7a4f5071d..29d957831 100644 --- a/src/world/light/LightPopulationTask.php +++ b/src/world/light/LightPopulationTask.php @@ -44,7 +44,7 @@ class LightPopulationTask extends AsyncTask{ private string $resultBlockLightArrays; /** - * @phpstan-param \Closure(array $blockLight, array $skyLight, array $heightMap) : void $onCompletion + * @phpstan-param \Closure(array $blockLight, array $skyLight, non-empty-list $heightMap) : void $onCompletion */ public function __construct(Chunk $chunk, \Closure $onCompletion){ $this->chunk = FastChunkSerializer::serializeTerrain($chunk); @@ -80,7 +80,10 @@ class LightPopulationTask extends AsyncTask{ } public function onCompletion() : void{ - /** @var int[] $heightMapArray */ + /** + * @var int[] $heightMapArray + * @phpstan-var non-empty-list $heightMapArray + */ $heightMapArray = igbinary_unserialize($this->resultHeightMap); /** @var LightArray[] $skyLightArrays */ @@ -90,7 +93,7 @@ class LightPopulationTask extends AsyncTask{ /** * @var \Closure - * @phpstan-var \Closure(array $blockLight, array $skyLight, array $heightMap) : void + * @phpstan-var \Closure(array $blockLight, array $skyLight, non-empty-list $heightMap) : void */ $callback = $this->fetchLocal(self::TLS_KEY_COMPLETION_CALLBACK); $callback($blockLightArrays, $skyLightArrays, $heightMapArray); diff --git a/tests/phpstan/configs/actual-problems.neon b/tests/phpstan/configs/actual-problems.neon index 1bb9329f0..f55fe1cbc 100644 --- a/tests/phpstan/configs/actual-problems.neon +++ b/tests/phpstan/configs/actual-problems.neon @@ -791,7 +791,7 @@ parameters: path: ../../../src/utils/Config.php - - message: "#^Parameter \\#1 \\$config of static method pocketmine\\\\utils\\\\Config\\:\\:writeProperties\\(\\) expects array\\, array\\ given\\.$#" + message: "#^Parameter \\#1 \\$config of static method pocketmine\\\\utils\\\\Config\\:\\:writeProperties\\(\\) expects array\\, array\\ given\\.$#" count: 1 path: ../../../src/utils/Config.php diff --git a/tests/phpstan/configs/phpstan-bugs.neon b/tests/phpstan/configs/phpstan-bugs.neon index 1ae740d66..0ee2b68a0 100644 --- a/tests/phpstan/configs/phpstan-bugs.neon +++ b/tests/phpstan/configs/phpstan-bugs.neon @@ -1,20 +1,5 @@ parameters: ignoreErrors: - - - message: "#^Method pocketmine\\\\block\\\\CakeWithCandle\\:\\:onInteractCandle\\(\\) has parameter \\$returnedItems with no value type specified in iterable type array\\.$#" - count: 1 - path: ../../../src/block/CakeWithCandle.php - - - - message: "#^Method pocketmine\\\\block\\\\CopperDoor\\:\\:onInteractCopper\\(\\) has parameter \\$returnedItems with no value type specified in iterable type array\\.$#" - count: 1 - path: ../../../src/block/CopperDoor.php - - - - message: "#^Method pocketmine\\\\block\\\\CopperTrapdoor\\:\\:onInteractCopper\\(\\) has parameter \\$returnedItems with no value type specified in iterable type array\\.$#" - count: 1 - path: ../../../src/block/CopperTrapdoor.php - - message: "#^Method pocketmine\\\\block\\\\DoubleTallGrass\\:\\:traitGetDropsForIncompatibleTool\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 diff --git a/tests/phpstan/configs/spl-fixed-array-sucks.neon b/tests/phpstan/configs/spl-fixed-array-sucks.neon index daa6361dd..7c2b2b91a 100644 --- a/tests/phpstan/configs/spl-fixed-array-sucks.neon +++ b/tests/phpstan/configs/spl-fixed-array-sucks.neon @@ -16,7 +16,7 @@ parameters: path: ../../../src/world/format/Chunk.php - - message: "#^Method pocketmine\\\\world\\\\format\\\\HeightArray\\:\\:getValues\\(\\) should return array\\ but returns array\\\\.$#" + message: "#^Method pocketmine\\\\world\\\\format\\\\HeightArray\\:\\:getValues\\(\\) should return non\\-empty\\-array\\ but returns array\\\\.$#" count: 1 path: ../../../src/world/format/HeightArray.php diff --git a/tests/phpunit/block/BlockTypeIdsTest.php b/tests/phpunit/block/BlockTypeIdsTest.php index ce21a89ab..cbfc07eaf 100644 --- a/tests/phpunit/block/BlockTypeIdsTest.php +++ b/tests/phpunit/block/BlockTypeIdsTest.php @@ -35,8 +35,12 @@ class BlockTypeIdsTest extends TestCase{ $constants = $reflect->getConstants(); unset($constants['FIRST_UNUSED_BLOCK_ID']); + self::assertNotEmpty($constants, "We should never have zero type IDs"); - self::assertSame($reflect->getConstant('FIRST_UNUSED_BLOCK_ID'), max($constants) + 1, "FIRST_UNUSED_BLOCK_ID must be one higher than the highest fixed type ID"); + $max = max($constants); + self::assertIsInt($max, "Max type ID should always be an integer"); + + self::assertSame($reflect->getConstant('FIRST_UNUSED_BLOCK_ID'), $max + 1, "FIRST_UNUSED_BLOCK_ID must be one higher than the highest fixed type ID"); } public function testNoDuplicates() : void{ diff --git a/tests/phpunit/item/ItemTypeIdsTest.php b/tests/phpunit/item/ItemTypeIdsTest.php index 7336780b3..a30489f07 100644 --- a/tests/phpunit/item/ItemTypeIdsTest.php +++ b/tests/phpunit/item/ItemTypeIdsTest.php @@ -35,8 +35,12 @@ class ItemTypeIdsTest extends TestCase{ $constants = $reflect->getConstants(); unset($constants['FIRST_UNUSED_ITEM_ID']); + self::assertNotEmpty($constants, "We should never have zero type IDs"); - self::assertSame($reflect->getConstant('FIRST_UNUSED_ITEM_ID'), max($constants) + 1, "FIRST_UNUSED_ITEM_ID must be one higher than the highest fixed type ID"); + $max = max($constants); + self::assertIsInt($max, "Max type ID should always be an integer"); + + self::assertSame($reflect->getConstant('FIRST_UNUSED_ITEM_ID'), $max + 1, "FIRST_UNUSED_ITEM_ID must be one higher than the highest fixed type ID"); } public function testNoDuplicates() : void{