Merge 'minor-next' into 'major-next'

Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/12643390650
This commit is contained in:
pmmp-admin-bot[bot] 2025-01-07 01:24:48 +00:00
commit 708784b0a2
74 changed files with 156 additions and 230 deletions

View File

@ -253,12 +253,12 @@ final class MemoryDump{
} }
/** /**
* @param object[] $objects reference parameter * @param object[]|true[] $objects reference parameter
* @param int[] $refCounts reference parameter * @param int[] $refCounts reference parameter
* *
* @phpstan-param array<string, object> $objects * @phpstan-param array<string, object|true> $objects
* @phpstan-param array<string, int> $refCounts * @phpstan-param array<string, int> $refCounts
* @phpstan-param-out array<string, object> $objects * @phpstan-param-out array<string, object|true> $objects
* @phpstan-param-out array<string, int> $refCounts * @phpstan-param-out array<string, int> $refCounts
*/ */
private static function continueDump(mixed $from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : mixed{ private static function continueDump(mixed $from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : mixed{

View File

@ -70,9 +70,6 @@ class Anvil extends Transparent implements Fallable{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)]; return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)];
} }

View File

@ -87,9 +87,6 @@ class Bamboo extends Transparent{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
//this places the BB at the northwest corner, not the center //this places the BB at the northwest corner, not the center
$inset = 1 - (($this->thick ? 3 : 2) / 16); $inset = 1 - (($this->thick ? 3 : 2) / 16);

View File

@ -30,7 +30,6 @@ use pocketmine\block\utils\SupportType;
use pocketmine\item\Banner as ItemBanner; use pocketmine\item\Banner as ItemBanner;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\VanillaItems; use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\world\BlockTransaction; use pocketmine\world\BlockTransaction;
@ -97,9 +96,6 @@ abstract class BaseBanner extends Transparent{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return []; return [];
} }

View File

@ -34,7 +34,6 @@ use pocketmine\event\block\SignChangeEvent;
use pocketmine\item\Dye; use pocketmine\item\Dye;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds; use pocketmine\item\ItemTypeIds;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\utils\TextFormat; use pocketmine\utils\TextFormat;
@ -95,9 +94,6 @@ abstract class BaseSign extends Transparent{
return 16; return 16;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return []; return [];
} }

View File

@ -76,9 +76,6 @@ class Bed extends Transparent{
} }
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)]; return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
} }

View File

@ -75,7 +75,10 @@ class Block{
protected BlockTypeInfo $typeInfo; protected BlockTypeInfo $typeInfo;
protected Position $position; protected Position $position;
/** @var AxisAlignedBB[]|null */ /**
* @var AxisAlignedBB[]|null
* @phpstan-var list<AxisAlignedBB>|null
*/
protected ?array $collisionBoxes = null; protected ?array $collisionBoxes = null;
private int $requiredBlockItemStateDataBits; private int $requiredBlockItemStateDataBits;
@ -907,6 +910,7 @@ class Block{
* - anti-cheat checks in plugins * - anti-cheat checks in plugins
* *
* @return AxisAlignedBB[] * @return AxisAlignedBB[]
* @phpstan-return list<AxisAlignedBB>
*/ */
final public function getCollisionBoxes() : array{ final public function getCollisionBoxes() : array{
if($this->collisionBoxes === null){ if($this->collisionBoxes === null){
@ -931,6 +935,7 @@ class Block{
/** /**
* @return AxisAlignedBB[] * @return AxisAlignedBB[]
* @phpstan-return list<AxisAlignedBB>
*/ */
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()]; return [AxisAlignedBB::one()];

View File

@ -95,7 +95,7 @@ class BlockBreakInfo{
* Returns whether this block can be instantly broken. * Returns whether this block can be instantly broken.
*/ */
public function breaksInstantly() : bool{ public function breaksInstantly() : bool{
return $this->hardness == 0.0; return $this->hardness === 0.0;
} }
/** /**

View File

@ -43,9 +43,6 @@ class Cactus extends Transparent{
return true; return true;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
$shrinkSize = 1 / 16; $shrinkSize = 1 / 16;
return [AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize)]; return [AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize)];

View File

@ -40,9 +40,6 @@ class Cake extends BaseCake{
$w->boundedIntAuto(0, self::MAX_BITES, $this->bites); $w->boundedIntAuto(0, self::MAX_BITES, $this->bites);
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [ return [
AxisAlignedBB::one() AxisAlignedBB::one()

View File

@ -36,9 +36,6 @@ class CakeWithCandle extends BaseCake{
onInteract as onInteractCandle; onInteract as onInteractCandle;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [ return [
AxisAlignedBB::one() AxisAlignedBB::one()

View File

@ -36,9 +36,6 @@ class Carpet extends Flowable{
return true; return true;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 15 / 16)]; return [AxisAlignedBB::one()->trim(Facing::UP, 15 / 16)];
} }

View File

@ -36,9 +36,6 @@ use pocketmine\player\Player;
class Chest extends Transparent{ class Chest extends Transparent{
use FacesOppositePlacingPlayerTrait; use FacesOppositePlacingPlayerTrait;
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
//these are slightly bigger than in PC //these are slightly bigger than in PC
return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)]; return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)];

View File

@ -50,9 +50,6 @@ class CocoaBlock extends Flowable{
$w->boundedIntAuto(0, self::MAX_AGE, $this->age); $w->boundedIntAuto(0, self::MAX_AGE, $this->age);
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [ return [
AxisAlignedBB::one() AxisAlignedBB::one()

View File

@ -62,9 +62,6 @@ class DaylightSensor extends Transparent{
return 300; return 300;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 10 / 16)]; return [AxisAlignedBB::one()->trim(Facing::UP, 10 / 16)];
} }

View File

@ -95,9 +95,6 @@ class Door extends Transparent{
return false; return false;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
//TODO: doors are 0.1825 blocks thick, instead of 0.1875 like JE (https://bugs.mojang.com/browse/MCPE-19214) //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)]; return [AxisAlignedBB::one()->trim($this->open ? Facing::rotateY($this->facing, !$this->hingeRight) : $this->facing, 327 / 400)];

View File

@ -33,9 +33,6 @@ use pocketmine\player\Player;
class EnchantingTable extends Transparent{ class EnchantingTable extends Transparent{
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 0.25)]; return [AxisAlignedBB::one()->trim(Facing::UP, 0.25)];
} }

View File

@ -50,9 +50,6 @@ class EndPortalFrame extends Opaque{
return 1; return 1;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 3 / 16)]; return [AxisAlignedBB::one()->trim(Facing::UP, 3 / 16)];
} }

View File

@ -52,9 +52,6 @@ class EndRod extends Flowable{
return 14; return 14;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
$myAxis = Facing::axis($this->facing); $myAxis = Facing::axis($this->facing);

View File

@ -40,9 +40,6 @@ class EnderChest extends Transparent{
return 7; return 7;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
//these are slightly bigger than in PC //these are slightly bigger than in PC
return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)]; return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)];

View File

@ -94,9 +94,6 @@ class Farmland extends Transparent{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)]; return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)];
} }

View File

@ -54,13 +54,9 @@ class Fence extends Transparent{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
$inset = 0.5 - $this->getThickness() / 2; $inset = 0.5 - $this->getThickness() / 2;
/** @var AxisAlignedBB[] $bbs */
$bbs = []; $bbs = [];
$connectWest = isset($this->connections[Facing::WEST]); $connectWest = isset($this->connections[Facing::WEST]);

View File

@ -64,9 +64,6 @@ class FenceGate extends Transparent{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return $this->open ? [] : [AxisAlignedBB::one()->extend(Facing::UP, 0.5)->squash(Facing::axis($this->facing), 6 / 16)]; return $this->open ? [] : [AxisAlignedBB::one()->extend(Facing::UP, 0.5)->squash(Facing::axis($this->facing), 6 / 16)];
} }

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
/** /**
@ -46,9 +45,6 @@ abstract class Flowable extends Transparent{
parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock); parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return []; return [];
} }

View File

@ -83,9 +83,6 @@ class FlowerPot extends Flowable{
return $block->hasTypeTag(BlockTypeTags::POTTABLE_PLANTS); return $block->hasTypeTag(BlockTypeTags::POTTABLE_PLANTS);
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->contract(3 / 16, 0, 3 / 16)->trim(Facing::UP, 5 / 8)]; return [AxisAlignedBB::one()->contract(3 / 16, 0, 3 / 16)->trim(Facing::UP, 5 / 8)];
} }

View File

@ -28,7 +28,6 @@ use pocketmine\block\utils\MultiAnySupportTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\item\Fertilizer; use pocketmine\item\Fertilizer;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing; use pocketmine\math\Facing;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\player\Player; use pocketmine\player\Player;
@ -47,9 +46,6 @@ class GlowLichen extends Transparent{
return false; return false;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return []; return [];
} }

View File

@ -29,9 +29,6 @@ use pocketmine\math\Facing;
class GrassPath extends Transparent{ class GrassPath extends Transparent{
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)]; return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)];
} }

View File

@ -58,9 +58,6 @@ class Ladder extends Transparent{
return true; return true;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim($this->facing, 13 / 16)]; return [AxisAlignedBB::one()->trim($this->facing, 13 / 16)];
} }

View File

@ -59,9 +59,6 @@ class Lantern extends Transparent{
return $this->lightLevel; return $this->lightLevel;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [ return [
AxisAlignedBB::one() AxisAlignedBB::one()

View File

@ -30,7 +30,6 @@ use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\event\block\BlockSpreadEvent; use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing; use pocketmine\math\Facing;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
@ -89,9 +88,6 @@ abstract class Liquid extends Transparent{
return false; return false;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return []; return [];
} }

View File

@ -104,9 +104,6 @@ class MobHead extends Flowable{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
$collisionBox = AxisAlignedBB::one() $collisionBox = AxisAlignedBB::one()
->contract(0.25, 0, 0.25) ->contract(0.25, 0, 0.25)

View File

@ -28,7 +28,6 @@ use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\Axis; use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
class NetherPortal extends Transparent{ class NetherPortal extends Transparent{
@ -62,9 +61,6 @@ class NetherPortal extends Transparent{
return false; return false;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return []; return [];
} }

View File

@ -79,9 +79,6 @@ class RedstoneComparator extends Flowable{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)]; return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)];
} }

View File

@ -62,9 +62,6 @@ class RedstoneRepeater extends Flowable{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)]; return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)];
} }

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\world\BlockTransaction; use pocketmine\world\BlockTransaction;
@ -70,9 +69,6 @@ class SeaPickle extends Transparent{
return $this->underwater ? ($this->count + 1) * 3 : 0; return $this->underwater ? ($this->count + 1) * 3 : 0;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return []; return [];
} }

View File

@ -93,9 +93,6 @@ class Slab extends Transparent{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
if($this->slabType === SlabType::DOUBLE){ if($this->slabType === SlabType::DOUBLE){
return [AxisAlignedBB::one()]; return [AxisAlignedBB::one()];

View File

@ -65,9 +65,6 @@ class SnowLayer extends Flowable implements Fallable{
return $this->layers < self::MAX_LAYERS; return $this->layers < self::MAX_LAYERS;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
//TODO: this zero-height BB is intended to stay in lockstep with a MCPE bug //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)]; return [AxisAlignedBB::one()->trim(Facing::UP, $this->layers >= 4 ? 0.5 : 1)];

View File

@ -28,9 +28,6 @@ use pocketmine\math\Facing;
class SoulSand extends Opaque{ class SoulSand extends Opaque{
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 8)]; return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 8)];
} }

View File

@ -56,7 +56,6 @@ class Thin extends Transparent{
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
$inset = 7 / 16; $inset = 7 / 16;
/** @var AxisAlignedBB[] $bbs */
$bbs = []; $bbs = [];
if(isset($this->connections[Facing::WEST]) || isset($this->connections[Facing::EAST])){ if(isset($this->connections[Facing::WEST]) || isset($this->connections[Facing::EAST])){

View File

@ -62,9 +62,6 @@ class Trapdoor extends Transparent{
return $this; return $this;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim($this->open ? $this->facing : ($this->top ? Facing::DOWN : Facing::UP), 13 / 16)]; return [AxisAlignedBB::one()->trim($this->open ? $this->facing : ($this->top ? Facing::DOWN : Facing::UP), 13 / 16)];
} }

View File

@ -33,9 +33,6 @@ class WaterLily extends Flowable{
canBePlacedAt as supportedWhenPlacedAt; canBePlacedAt as supportedWhenPlacedAt;
} }
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->contract(1 / 16, 0, 1 / 16)->trim(Facing::UP, 63 / 64)]; return [AxisAlignedBB::one()->contract(1 / 16, 0, 1 / 16)->trim(Facing::UP, 63 / 64)];
} }

View File

@ -43,7 +43,10 @@ trait CandleTrait{
return $this->lit ? 3 : 0; 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{ 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($item->getTypeId() === ItemTypeIds::FIRE_CHARGE || $item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($this->lit){ if($this->lit){

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block\utils; namespace pocketmine\block\utils;
use pocketmine\block\Block;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Axe; use pocketmine\item\Axe;
use pocketmine\item\Item; use pocketmine\item\Item;
@ -58,6 +59,10 @@ trait CopperTrait{
return $this; return $this;
} }
/**
* @param Item[] &$returnedItems
* @see Block::onInteract()
*/
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(!$this->waxed && $item->getTypeId() === ItemTypeIds::HONEYCOMB){ if(!$this->waxed && $item->getTypeId() === ItemTypeIds::HONEYCOMB){
$this->waxed = true; $this->waxed = true;

View File

@ -33,6 +33,7 @@ use pocketmine\permission\PermissionManager;
use pocketmine\Server; use pocketmine\Server;
use pocketmine\utils\BroadcastLoggerForwarder; use pocketmine\utils\BroadcastLoggerForwarder;
use pocketmine\utils\TextFormat; use pocketmine\utils\TextFormat;
use function array_values;
use function explode; use function explode;
use function implode; use function implode;
use function str_replace; use function str_replace;
@ -80,6 +81,7 @@ abstract class Command{
/** /**
* @param string[] $args * @param string[] $args
* @phpstan-param list<string> $args
* *
* @return mixed * @return mixed
* @throws CommandException * @throws CommandException
@ -213,6 +215,7 @@ abstract class Command{
* @phpstan-param list<string> $aliases * @phpstan-param list<string> $aliases
*/ */
public function setAliases(array $aliases) : void{ public function setAliases(array $aliases) : void{
$aliases = array_values($aliases); //because plugins can and will pass crap
$this->aliases = $aliases; $this->aliases = $aliases;
if(!$this->isRegistered()){ if(!$this->isRegistered()){
$this->activeAliases = $aliases; $this->activeAliases = $aliases;

View File

@ -121,6 +121,7 @@ class FormattedCommandAlias extends Command{
/** /**
* @param string[] $args * @param string[] $args
* @phpstan-param list<string> $args
*/ */
private function buildCommand(string $formatString, array $args) : ?string{ private function buildCommand(string $formatString, array $args) : ?string{
$index = 0; $index = 0;

View File

@ -73,6 +73,7 @@ use pocketmine\timings\Timings;
use pocketmine\utils\TextFormat; use pocketmine\utils\TextFormat;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use function array_shift; use function array_shift;
use function array_values;
use function count; use function count;
use function implode; use function implode;
use function str_contains; use function str_contains;
@ -163,7 +164,7 @@ class SimpleCommandMap implements CommandMap{
unset($aliases[$index]); unset($aliases[$index]);
} }
} }
$command->setAliases($aliases); $command->setAliases(array_values($aliases));
if(!$registered){ if(!$registered){
$command->setLabel($fallbackPrefix . ":" . $label); $command->setLabel($fallbackPrefix . ":" . $label);

View File

@ -46,6 +46,8 @@ use function fwrite;
use function http_build_query; use function http_build_query;
use function implode; use function implode;
use function is_array; use function is_array;
use function is_int;
use function is_string;
use function json_decode; use function json_decode;
use function mkdir; use function mkdir;
use function strtolower; use function strtolower;
@ -178,7 +180,7 @@ class TimingsCommand extends VanillaCommand{
return; return;
} }
$response = json_decode($result->getBody(), true); $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( Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead(
"https://" . $host . "/?id=" . $response["id"])); "https://" . $host . "/?id=" . $response["id"]));
}else{ }else{

View File

@ -76,7 +76,7 @@ class Attribute{
throw new \InvalidArgumentException("Minimum $minValue is greater than the maximum $max"); throw new \InvalidArgumentException("Minimum $minValue is greater than the maximum $max");
} }
if($this->minValue != $minValue){ if($this->minValue !== $minValue){
$this->desynchronized = true; $this->desynchronized = true;
$this->minValue = $minValue; $this->minValue = $minValue;
} }
@ -95,7 +95,7 @@ class Attribute{
throw new \InvalidArgumentException("Maximum $maxValue is less than the minimum $min"); throw new \InvalidArgumentException("Maximum $maxValue is less than the minimum $min");
} }
if($this->maxValue != $maxValue){ if($this->maxValue !== $maxValue){
$this->desynchronized = true; $this->desynchronized = true;
$this->maxValue = $maxValue; $this->maxValue = $maxValue;
} }
@ -140,7 +140,7 @@ class Attribute{
$value = min(max($value, $this->getMinValue()), $this->getMaxValue()); $value = min(max($value, $this->getMinValue()), $this->getMaxValue());
} }
if($this->currentValue != $value){ if($this->currentValue !== $value){
$this->desynchronized = true; $this->desynchronized = true;
$this->currentValue = $value; $this->currentValue = $value;
}elseif($forceSend){ }elseif($forceSend){

View File

@ -72,6 +72,7 @@ use function assert;
use function cos; use function cos;
use function count; use function count;
use function deg2rad; use function deg2rad;
use function floatval;
use function floor; use function floor;
use function fmod; use function fmod;
use function get_class; 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 * Sets the health of the Entity. This won't send any update to the players
*/ */
public function setHealth(float $amount) : void{ public function setHealth(float $amount) : void{
if($amount == $this->health){ if($amount === $this->health){
return; return;
} }
@ -760,8 +761,8 @@ abstract class Entity{
$diffMotion = $this->motion->subtractVector($this->lastMotion)->lengthSquared(); $diffMotion = $this->motion->subtractVector($this->lastMotion)->lengthSquared();
$still = $this->motion->lengthSquared() == 0.0; $still = $this->motion->lengthSquared() === 0.0;
$wasStill = $this->lastMotion->lengthSquared() == 0.0; $wasStill = $this->lastMotion->lengthSquared() === 0.0;
if($wasStill !== $still){ if($wasStill !== $still){
//TODO: hack for client-side AI interference: prevent client sided movement when motion is 0 //TODO: hack for client-side AI interference: prevent client sided movement when motion is 0
$this->setNoClientPredictions($still); $this->setNoClientPredictions($still);
@ -1004,7 +1005,7 @@ abstract class Entity{
abs($this->motion->z) <= self::MOTION_THRESHOLD ? 0 : null 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); $this->move($this->motion->x, $this->motion->y, $this->motion->z);
} }
@ -1058,9 +1059,9 @@ abstract class Entity{
public function hasMovementUpdate() : bool{ public function hasMovementUpdate() : bool{
return ( return (
$this->forceMovementUpdate || $this->forceMovementUpdate ||
$this->motion->x != 0 || floatval($this->motion->x) !== 0.0 ||
$this->motion->y != 0 || floatval($this->motion->y) !== 0.0 ||
$this->motion->z != 0 || floatval($this->motion->z) !== 0.0 ||
!$this->onGround !$this->onGround
); );
} }
@ -1163,7 +1164,7 @@ abstract class Entity{
$moveBB->offset(0, $dy, 0); $moveBB->offset(0, $dy, 0);
$fallingFlag = ($this->onGround || ($dy != $wantedY && $wantedY < 0)); $fallingFlag = ($this->onGround || ($dy !== $wantedY && $wantedY < 0));
foreach($list as $bb){ foreach($list as $bb){
$dx = $bb->calculateXOffset($moveBB, $dx); $dx = $bb->calculateXOffset($moveBB, $dx);
@ -1177,7 +1178,7 @@ abstract class Entity{
$moveBB->offset(0, 0, $dz); $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; $cx = $dx;
$cy = $dy; $cy = $dy;
$cz = $dz; $cz = $dz;
@ -1242,9 +1243,9 @@ abstract class Entity{
$postFallVerticalVelocity = $this->updateFallState($dy, $this->onGround); $postFallVerticalVelocity = $this->updateFallState($dy, $this->onGround);
$this->motion = $this->motion->withComponents( $this->motion = $this->motion->withComponents(
$wantedX != $dx ? 0 : null, $wantedX !== $dx ? 0 : null,
$postFallVerticalVelocity ?? ($wantedY != $dy ? 0 : null), $postFallVerticalVelocity ?? ($wantedY !== $dy ? 0 : null),
$wantedZ != $dz ? 0 : null $wantedZ !== $dz ? 0 : null
); );
//TODO: vehicle collision events (first we need to spawn them!) //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{ protected function checkGroundState(float $wantedX, float $wantedY, float $wantedZ, float $dx, float $dy, float $dz) : void{
$this->isCollidedVertically = $wantedY != $dy; $this->isCollidedVertically = $wantedY !== $dy;
$this->isCollidedHorizontally = ($wantedX != $dx || $wantedZ != $dz); $this->isCollidedHorizontally = ($wantedX !== $dx || $wantedZ !== $dz);
$this->isCollided = ($this->isCollidedHorizontally || $this->isCollidedVertically); $this->isCollided = ($this->isCollidedHorizontally || $this->isCollidedVertically);
$this->onGround = ($wantedY != $dy && $wantedY < 0); $this->onGround = ($wantedY !== $dy && $wantedY < 0);
} }
/** /**

View File

@ -66,7 +66,7 @@ class Location extends Position{
public function equals(Vector3 $v) : bool{ public function equals(Vector3 $v) : bool{
if($v instanceof Location){ 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); return parent::equals($v);
} }

View File

@ -118,7 +118,6 @@ use pocketmine\world\Position;
use pocketmine\world\World; use pocketmine\world\World;
use pocketmine\YmlServerProperties; use pocketmine\YmlServerProperties;
use function array_map; use function array_map;
use function array_values;
use function base64_encode; use function base64_encode;
use function bin2hex; use function bin2hex;
use function count; use function count;
@ -164,7 +163,10 @@ class NetworkSession{
private ?EncryptionContext $cipher = null; private ?EncryptionContext $cipher = null;
/** @var string[] */ /**
* @var string[]
* @phpstan-var list<string>
*/
private array $sendBuffer = []; private array $sendBuffer = [];
/** /**
* @var PromiseResolver[] * @var PromiseResolver[]
@ -544,6 +546,7 @@ class NetworkSession{
* @phpstan-return Promise<true> * @phpstan-return Promise<true>
*/ */
public function sendDataPacketWithReceipt(ClientboundPacket $packet, bool $immediate = false) : Promise{ public function sendDataPacketWithReceipt(ClientboundPacket $packet, bool $immediate = false) : Promise{
/** @phpstan-var PromiseResolver<true> $resolver */
$resolver = new PromiseResolver(); $resolver = new PromiseResolver();
if(!$this->sendDataPacketInternal($packet, $immediate, $resolver)){ 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 //work around a client bug which makes the original name not show when aliases are used
$aliases[] = $lname; $aliases[] = $lname;
} }
$aliasObj = new CommandEnum(ucfirst($command->getLabel()) . "Aliases", array_values($aliases)); $aliasObj = new CommandEnum(ucfirst($command->getLabel()) . "Aliases", $aliases);
} }
$description = $command->getDescription(); $description = $command->getDescription();

View File

@ -416,7 +416,7 @@ class InGamePacketHandler extends PacketHandler{
$droppedCount = null; $droppedCount = null;
foreach($data->getActions() as $networkInventoryAction){ 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(); $droppedCount = $networkInventoryAction->newItem->getItemStack()->getCount();
if($droppedCount <= 0){ if($droppedCount <= 0){
throw new PacketHandlingException("Expected positive count for dropped item"); throw new PacketHandlingException("Expected positive count for dropped item");
@ -578,7 +578,7 @@ class InGamePacketHandler extends PacketHandler{
private function handleReleaseItemTransaction(ReleaseItemTransactionData $data) : bool{ private function handleReleaseItemTransaction(ReleaseItemTransactionData $data) : bool{
$this->player->selectHotbarSlot($data->getHotbarSlot()); $this->player->selectHotbarSlot($data->getHotbarSlot());
if($data->getActionType() == ReleaseItemTransactionData::ACTION_RELEASE){ if($data->getActionType() === ReleaseItemTransactionData::ACTION_RELEASE){
$this->player->releaseHeldItem(); $this->player->releaseHeldItem();
return true; return true;
} }

View File

@ -84,11 +84,20 @@ class PluginDescription{
* @phpstan-var array<string, list<string>> * @phpstan-var array<string, list<string>>
*/ */
private array $extensions = []; private array $extensions = [];
/** @var string[] */ /**
* @var string[]
* @phpstan-var list<string>
*/
private array $depend = []; private array $depend = [];
/** @var string[] */ /**
* @var string[]
* @phpstan-var list<string>
*/
private array $softDepend = []; private array $softDepend = [];
/** @var string[] */ /**
* @var string[]
* @phpstan-var list<string>
*/
private array $loadBefore = []; private array $loadBefore = [];
private string $version; private string $version;
/** /**
@ -173,7 +182,7 @@ class PluginDescription{
} }
if(isset($plugin[self::KEY_DEPEND])){ 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])){ if(isset($plugin[self::KEY_EXTENSIONS])){
$extensions = (array) $plugin[self::KEY_EXTENSIONS]; $extensions = (array) $plugin[self::KEY_EXTENSIONS];
@ -183,13 +192,13 @@ class PluginDescription{
$k = $v; $k = $v;
$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); $this->website = (string) ($plugin[self::KEY_WEBSITE] ?? $this->website);
@ -210,7 +219,7 @@ class PluginDescription{
$this->authors = []; $this->authors = [];
if(isset($plugin[self::KEY_AUTHOR])){ if(isset($plugin[self::KEY_AUTHOR])){
if(is_array($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{ }else{
$this->authors[] = $plugin[self::KEY_AUTHOR]; $this->authors[] = $plugin[self::KEY_AUTHOR];
} }
@ -284,6 +293,7 @@ class PluginDescription{
/** /**
* @return string[] * @return string[]
* @phpstan-return list<string>
*/ */
public function getDepend() : array{ public function getDepend() : array{
return $this->depend; return $this->depend;
@ -295,6 +305,7 @@ class PluginDescription{
/** /**
* @return string[] * @return string[]
* @phpstan-return list<string>
*/ */
public function getLoadBefore() : array{ public function getLoadBefore() : array{
return $this->loadBefore; return $this->loadBefore;
@ -324,6 +335,7 @@ class PluginDescription{
/** /**
* @return string[] * @return string[]
* @phpstan-return list<string>
*/ */
public function getSoftDepend() : array{ public function getSoftDepend() : array{
return $this->softDepend; return $this->softDepend;

View File

@ -31,12 +31,12 @@ final class PluginLoadTriage{
public array $plugins = []; public array $plugins = [];
/** /**
* @var string[][] * @var string[][]
* @phpstan-var array<string, list<string>> * @phpstan-var array<string, array<string>>
*/ */
public array $dependencies = []; public array $dependencies = [];
/** /**
* @var string[][] * @var string[][]
* @phpstan-var array<string, list<string>> * @phpstan-var array<string, array<string>>
*/ */
public array $softDependencies = []; public array $softDependencies = [];
} }

View File

@ -327,12 +327,12 @@ class PluginManager{
* @param string[][] $dependencyLists * @param string[][] $dependencyLists
* @param Plugin[] $loadedPlugins * @param Plugin[] $loadedPlugins
* *
* @phpstan-param array<string, list<string>> $dependencyLists * @phpstan-param array<string, array<string>> $dependencyLists
* @phpstan-param-out array<string, list<string>> $dependencyLists * @phpstan-param-out array<string, array<string>> $dependencyLists
*/ */
private function checkDepsForTriage(string $pluginName, string $dependencyType, array &$dependencyLists, array $loadedPlugins, PluginLoadTriage $triage) : void{ private function checkDepsForTriage(string $pluginName, string $dependencyType, array &$dependencyLists, array $loadedPlugins, PluginLoadTriage $triage) : void{
if(isset($dependencyLists[$pluginName])){ 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){ if(isset($loadedPlugins[$dependency]) || $this->getPlugin($dependency) instanceof Plugin){
$this->server->getLogger()->debug("Successfully resolved $dependencyType dependency \"$dependency\" for plugin \"$pluginName\""); $this->server->getLogger()->debug("Successfully resolved $dependencyType dependency \"$dependency\" for plugin \"$pluginName\"");
unset($dependencyLists[$pluginName][$key]); unset($dependencyLists[$pluginName][$key]);
@ -399,7 +399,7 @@ class PluginManager{
//check for skippable soft dependencies first, in case the dependents could resolve hard dependencies //check for skippable soft dependencies first, in case the dependents could resolve hard dependencies
foreach(Utils::stringifyKeys($triage->plugins) as $name => $file){ foreach(Utils::stringifyKeys($triage->plugins) as $name => $file){
if(isset($triage->softDependencies[$name]) && !isset($triage->dependencies[$name])){ 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)){ 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\""); $this->server->getLogger()->debug("Skipping resolution of missing soft dependency \"$dependency\" for plugin \"$name\"");
unset($triage->softDependencies[$name][$k]); unset($triage->softDependencies[$name][$k]);
@ -416,7 +416,7 @@ class PluginManager{
if(isset($triage->dependencies[$name])){ if(isset($triage->dependencies[$name])){
$unknownDependencies = []; $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)){ if($this->getPlugin($dependency) === null && !array_key_exists($dependency, $triage->plugins)){
//assume that the plugin is never going to be loaded //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 //by this point all soft dependencies have been ignored if they were able to be, so

View File

@ -72,7 +72,7 @@ class Config{
/** /**
* @var mixed[] * @var mixed[]
* @phpstan-var array<string, mixed> * @phpstan-var array<mixed, mixed>
*/ */
private array $config = []; private array $config = [];
@ -450,7 +450,7 @@ class Config{
/** /**
* @return mixed[] * @return mixed[]
* @phpstan-return list<string>|array<string, mixed> * @phpstan-return list<mixed>|array<mixed, mixed>
*/ */
public function getAll(bool $keys = false) : array{ public function getAll(bool $keys = false) : array{
return ($keys ? array_keys($this->config) : $this->config); return ($keys ? array_keys($this->config) : $this->config);
@ -458,7 +458,6 @@ class Config{
/** /**
* @param mixed[] $defaults * @param mixed[] $defaults
* @phpstan-param array<string, mixed> $defaults
*/ */
public function setDefaults(array $defaults) : void{ public function setDefaults(array $defaults) : void{
$this->fillDefaults($defaults, $this->config); $this->fillDefaults($defaults, $this->config);
@ -467,13 +466,11 @@ class Config{
/** /**
* @param mixed[] $default * @param mixed[] $default
* @param mixed[] $data reference parameter * @param mixed[] $data reference parameter
* @phpstan-param array<string, mixed> $default * @phpstan-param-out array<mixed, mixed> $data
* @phpstan-param array<string, mixed> $data
* @phpstan-param-out array<string, mixed> $data
*/ */
private function fillDefaults(array $default, array &$data) : int{ private function fillDefaults(array $default, array &$data) : int{
$changed = 0; $changed = 0;
foreach(Utils::stringifyKeys($default) as $k => $v){ foreach(Utils::promoteKeys($default) as $k => $v){
if(is_array($v)){ if(is_array($v)){
if(!isset($data[$k]) || !is_array($data[$k])){ if(!isset($data[$k]) || !is_array($data[$k])){
$data[$k] = []; $data[$k] = [];
@ -509,8 +506,8 @@ class Config{
} }
/** /**
* @param string[] $entries * @param string[]|int[] $entries
* @phpstan-param list<string> $entries * @phpstan-param list<int|string> $entries
*/ */
public static function writeList(array $entries) : string{ public static function writeList(array $entries) : string{
return implode("\n", $entries); return implode("\n", $entries);
@ -518,11 +515,11 @@ class Config{
/** /**
* @param string[]|int[]|float[]|bool[] $config * @param string[]|int[]|float[]|bool[] $config
* @phpstan-param array<string, string|int|float|bool> $config * @phpstan-param array<int|string, string|int|float|bool> $config
*/ */
public static function writeProperties(array $config) : string{ public static function writeProperties(array $config) : string{
$content = "#Properties Config file\r\n#" . date("D M j H:i:s T Y") . "\r\n"; $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)){ if(is_bool($v)){
$v = $v ? "on" : "off"; $v = $v ? "on" : "off";
} }
@ -534,7 +531,7 @@ class Config{
/** /**
* @return string[]|int[]|float[]|bool[] * @return string[]|int[]|float[]|bool[]
* @phpstan-return array<string, string|int|float|bool> * @phpstan-return array<int|string, string|int|float|bool>
*/ */
public static function parseProperties(string $content) : array{ public static function parseProperties(string $content) : array{
$result = []; $result = [];
@ -560,7 +557,7 @@ class Config{
}; };
break; break;
} }
$result[(string) $k] = $v; $result[$k] = $v;
} }
} }

View File

@ -39,7 +39,7 @@ final class Git{
* @param bool $dirty reference parameter, set to whether the repo has local changes * @param bool $dirty reference parameter, set to whether the repo has local changes
*/ */
public static function getRepositoryState(string $dir, bool &$dirty) : ?string{ 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 if(Process::execute("git -C \"$dir\" diff --quiet") === 1 || Process::execute("git -C \"$dir\" diff --cached --quiet") === 1){ //Locally-modified
$dirty = true; $dirty = true;
} }

View File

@ -100,7 +100,7 @@ class Internet{
} }
$ip = self::getURL("http://ifconfig.me/ip"); $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; return self::$ip = $addr;
} }
@ -157,22 +157,21 @@ class Internet{
* POSTs data to an URL * 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. * 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[]|string $args
* @param string[] $extraHeaders * @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. * @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<string, string> $args * @phpstan-param string|array<string, string> $args
* @phpstan-param list<string> $extraHeaders * @phpstan-param list<string> $extraHeaders
* @phpstan-param TErrorVar $err * @phpstan-param-out string|null $err
* @phpstan-param-out TErrorVar|string $err
*/ */
public static function postURL(string $page, array|string $args, int $timeout = 10, array $extraHeaders = [], &$err = null) : ?InternetRequestResult{ public static function postURL(string $page, array|string $args, int $timeout = 10, array $extraHeaders = [], &$err = null) : ?InternetRequestResult{
try{ try{
return self::simpleCurl($page, $timeout, $extraHeaders, [ $result = self::simpleCurl($page, $timeout, $extraHeaders, [
CURLOPT_POST => 1, CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $args CURLOPT_POSTFIELDS => $args
]); ]);
$err = null;
return $result;
}catch(InternetException $ex){ }catch(InternetException $ex){
$err = $ex->getMessage(); $err = $ex->getMessage();
return null; return null;

View File

@ -174,8 +174,17 @@ final class Process{
return -1; return -1;
} }
$stdout = stream_get_contents($pipes[1]); $out = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]); 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){ foreach($pipes as $p){
fclose($p); fclose($p);

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\utils; namespace pocketmine\utils;
/** /**
* @phpstan-template TPriority * @phpstan-template TPriority of numeric
* @phpstan-template TValue * @phpstan-template TValue
* @phpstan-extends \SplPriorityQueue<TPriority, TValue> * @phpstan-extends \SplPriorityQueue<TPriority, TValue>
*/ */

View File

@ -36,14 +36,12 @@ use const SIGTERM;
final class SignalHandler{ final class SignalHandler{
/** @phpstan-var (\Closure(int) : void)|null */ /** @phpstan-var (\Closure(int) : void)|null */
private ?\Closure $interruptCallback; private ?\Closure $interruptCallback = null;
/** /**
* @phpstan-param \Closure() : void $interruptCallback * @phpstan-param \Closure() : void $interruptCallback
*/ */
public function __construct(\Closure $interruptCallback){ public function __construct(\Closure $interruptCallback){
$this->interruptCallback = $interruptCallback;
if(function_exists('sapi_windows_set_ctrl_handler')){ if(function_exists('sapi_windows_set_ctrl_handler')){
sapi_windows_set_ctrl_handler($this->interruptCallback = function(int $signo) use ($interruptCallback) : void{ 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){ if($signo === PHP_WINDOWS_EVENT_CTRL_C || $signo === PHP_WINDOWS_EVENT_CTRL_BREAK){

View File

@ -134,7 +134,7 @@ abstract class Timezone{
$offset = $matches[2]; $offset = $matches[2];
if($offset == ""){ if($offset === ""){
return "UTC"; return "UTC";
} }
@ -156,7 +156,7 @@ abstract class Timezone{
$offset = trim(exec('date +%:z')); $offset = trim(exec('date +%:z'));
if($offset == "+00:00"){ if($offset === "+00:00"){
return "UTC"; return "UTC";
} }
@ -195,7 +195,7 @@ abstract class Timezone{
$offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second']; $offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];
//After date_parse is done, put the sign back //After date_parse is done, put the sign back
if($negative_offset == true){ if($negative_offset){
$offset = -abs($offset); $offset = -abs($offset);
} }
@ -204,7 +204,7 @@ abstract class Timezone{
//That's been a bug in PHP since 2008! //That's been a bug in PHP since 2008!
foreach(timezone_abbreviations_list() as $zones){ foreach(timezone_abbreviations_list() as $zones){
foreach($zones as $timezone){ foreach($zones as $timezone){
if($timezone['timezone_id'] !== null && $timezone['offset'] == $offset){ if($timezone['timezone_id'] !== null && $timezone['offset'] === $offset){
return $timezone['timezone_id']; return $timezone['timezone_id'];
} }
} }

View File

@ -220,7 +220,7 @@ final class Utils{
$mac = implode("\n", $mac); $mac = implode("\n", $mac);
if(preg_match_all("#Physical Address[. ]{1,}: ([0-9A-F\\-]{17})#", $mac, $matches) > 0){ if(preg_match_all("#Physical Address[. ]{1,}: ([0-9A-F\\-]{17})#", $mac, $matches) > 0){
foreach($matches[1] as $i => $v){ 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]); unset($matches[1][$i]);
} }
} }
@ -234,7 +234,7 @@ final class Utils{
$mac = implode("\n", $mac); $mac = implode("\n", $mac);
if(preg_match_all("#HWaddr[ \t]{1,}([0-9a-f:]{17})#", $mac, $matches) > 0){ if(preg_match_all("#HWaddr[ \t]{1,}([0-9a-f:]{17})#", $mac, $matches) > 0){
foreach($matches[1] as $i => $v){ 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]); unset($matches[1][$i]);
} }
} }

View File

@ -1364,7 +1364,7 @@ class World implements ChunkManager{
* TODO: phpstan can't infer these types yet :( * TODO: phpstan can't infer these types yet :(
* @phpstan-var array<int, LightArray> $blockLight * @phpstan-var array<int, LightArray> $blockLight
* @phpstan-var array<int, LightArray> $skyLight * @phpstan-var array<int, LightArray> $skyLight
* @phpstan-var array<int, int> $heightMap * @phpstan-var non-empty-list<int> $heightMap
*/ */
if($this->unloaded || ($chunk = $this->getChunk($chunkX, $chunkZ)) === null || $chunk->isLightPopulated() === true){ if($this->unloaded || ($chunk = $this->getChunk($chunkX, $chunkZ)) === null || $chunk->isLightPopulated() === true){
return; return;
@ -1562,6 +1562,7 @@ class World implements ChunkManager{
* Larger AABBs (>= 2 blocks on any axis) are not accounted for. * Larger AABBs (>= 2 blocks on any axis) are not accounted for.
* *
* @return AxisAlignedBB[] * @return AxisAlignedBB[]
* @phpstan-return list<AxisAlignedBB>
*/ */
private function getBlockCollisionBoxesForCell(int $x, int $y, int $z) : array{ private function getBlockCollisionBoxesForCell(int $x, int $y, int $z) : array{
$block = $this->getBlockAt($x, $y, $z); $block = $this->getBlockAt($x, $y, $z);
@ -2021,7 +2022,6 @@ class World implements ChunkManager{
* @phpstan-return list<ExperienceOrb> * @phpstan-return list<ExperienceOrb>
*/ */
public function dropExperience(Vector3 $pos, int $amount) : array{ public function dropExperience(Vector3 $pos, int $amount) : array{
/** @var ExperienceOrb[] $orbs */
$orbs = []; $orbs = [];
foreach(ExperienceOrb::splitIntoOrbSizes($amount) as $split){ foreach(ExperienceOrb::splitIntoOrbSizes($amount) as $split){
@ -3064,6 +3064,7 @@ class World implements ChunkManager{
* @phpstan-return Promise<Position> * @phpstan-return Promise<Position>
*/ */
public function requestSafeSpawn(?Vector3 $spawn = null) : Promise{ public function requestSafeSpawn(?Vector3 $spawn = null) : Promise{
/** @phpstan-var PromiseResolver<Position> $resolver */
$resolver = new PromiseResolver(); $resolver = new PromiseResolver();
$spawn ??= $this->getSpawnLocation(); $spawn ??= $this->getSpawnLocation();
/* /*
@ -3235,6 +3236,7 @@ class World implements ChunkManager{
private function enqueuePopulationRequest(int $chunkX, int $chunkZ, ?ChunkLoader $associatedChunkLoader) : Promise{ private function enqueuePopulationRequest(int $chunkX, int $chunkZ, ?ChunkLoader $associatedChunkLoader) : Promise{
$chunkHash = World::chunkHash($chunkX, $chunkZ); $chunkHash = World::chunkHash($chunkX, $chunkZ);
$this->addChunkHashToPopulationRequestQueue($chunkHash); $this->addChunkHashToPopulationRequestQueue($chunkHash);
/** @phpstan-var PromiseResolver<Chunk> $resolver */
$resolver = $this->chunkPopulationRequestMap[$chunkHash] = new PromiseResolver(); $resolver = $this->chunkPopulationRequestMap[$chunkHash] = new PromiseResolver();
if($associatedChunkLoader === null){ if($associatedChunkLoader === null){
$temporaryLoader = new class implements ChunkLoader{}; $temporaryLoader = new class implements ChunkLoader{};

View File

@ -57,7 +57,10 @@ class Chunk{
*/ */
protected \SplFixedArray $subChunks; protected \SplFixedArray $subChunks;
/** @var Tile[] */ /**
* @var Tile[]
* @phpstan-var array<int, Tile>
*/
protected array $tiles = []; protected array $tiles = [];
protected HeightArray $heightMap; protected HeightArray $heightMap;
@ -210,6 +213,7 @@ class Chunk{
/** /**
* @return Tile[] * @return Tile[]
* @phpstan-return array<int, Tile>
*/ */
public function getTiles() : array{ public function getTiles() : array{
return $this->tiles; return $this->tiles;
@ -237,6 +241,7 @@ class Chunk{
/** /**
* @return int[] * @return int[]
* @phpstan-return non-empty-list<int>
*/ */
public function getHeightMapArray() : array{ public function getHeightMapArray() : array{
return $this->heightMap->getValues(); return $this->heightMap->getValues();
@ -244,6 +249,7 @@ class Chunk{
/** /**
* @param int[] $values * @param int[] $values
* @phpstan-param non-empty-list<int> $values
*/ */
public function setHeightMapArray(array $values) : void{ public function setHeightMapArray(array $values) : void{
$this->heightMap = new HeightArray($values); $this->heightMap = new HeightArray($values);

View File

@ -36,7 +36,7 @@ final class HeightArray{
/** /**
* @param int[] $values ZZZZXXXX key bit order * @param int[] $values ZZZZXXXX key bit order
* @phpstan-param list<int> $values * @phpstan-param non-empty-list<int> $values
*/ */
public function __construct(array $values){ public function __construct(array $values){
if(count($values) !== 256){ if(count($values) !== 256){
@ -66,7 +66,7 @@ final class HeightArray{
/** /**
* @return int[] ZZZZXXXX key bit order * @return int[] ZZZZXXXX key bit order
* @phpstan-return list<int> * @phpstan-return non-empty-list<int>
*/ */
public function getValues() : array{ public function getValues() : array{
return $this->array->toArray(); return $this->array->toArray();

View File

@ -112,7 +112,6 @@ final class FastChunkSerializer{
$y = Binary::signByte($stream->getByte()); $y = Binary::signByte($stream->getByte());
$airBlockId = $stream->getInt(); $airBlockId = $stream->getInt();
/** @var PalettedBlockArray[] $layers */
$layers = []; $layers = [];
for($i = 0, $layerCount = $stream->getByte(); $i < $layerCount; ++$i){ for($i = 0, $layerCount = $stream->getByte(); $i < $layerCount; ++$i){
$layers[] = self::deserializePalettedArray($stream); $layers[] = self::deserializePalettedArray($stream);

View File

@ -93,10 +93,12 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
} }
/** /**
* @param int $regionX reference parameter * @param int|null $regionX reference parameter
* @param int $regionZ reference parameter * @param int|null $regionZ reference parameter
* @phpstan-param-out int $regionX * @phpstan-param-out int $regionX
* @phpstan-param-out int $regionZ * @phpstan-param-out int $regionZ
*
* TODO: make this private
*/ */
public static function getRegionIndex(int $chunkX, int $chunkZ, &$regionX, &$regionZ) : void{ public static function getRegionIndex(int $chunkX, int $chunkZ, &$regionX, &$regionZ) : void{
$regionX = $chunkX >> 5; $regionX = $chunkX >> 5;
@ -154,6 +156,8 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
/** /**
* @return CompoundTag[] * @return CompoundTag[]
* @phpstan-return list<CompoundTag>
*
* @throws CorruptedChunkException * @throws CorruptedChunkException
*/ */
protected static function getCompoundList(string $context, ListTag $list) : array{ protected static function getCompoundList(string $context, ListTag $list) : array{

View File

@ -44,7 +44,7 @@ class LightPopulationTask extends AsyncTask{
private string $resultBlockLightArrays; private string $resultBlockLightArrays;
/** /**
* @phpstan-param \Closure(array<int, LightArray> $blockLight, array<int, LightArray> $skyLight, array<int, int> $heightMap) : void $onCompletion * @phpstan-param \Closure(array<int, LightArray> $blockLight, array<int, LightArray> $skyLight, non-empty-list<int> $heightMap) : void $onCompletion
*/ */
public function __construct(Chunk $chunk, \Closure $onCompletion){ public function __construct(Chunk $chunk, \Closure $onCompletion){
$this->chunk = FastChunkSerializer::serializeTerrain($chunk); $this->chunk = FastChunkSerializer::serializeTerrain($chunk);
@ -80,7 +80,10 @@ class LightPopulationTask extends AsyncTask{
} }
public function onCompletion() : void{ public function onCompletion() : void{
/** @var int[] $heightMapArray */ /**
* @var int[] $heightMapArray
* @phpstan-var non-empty-list<int> $heightMapArray
*/
$heightMapArray = igbinary_unserialize($this->resultHeightMap); $heightMapArray = igbinary_unserialize($this->resultHeightMap);
/** @var LightArray[] $skyLightArrays */ /** @var LightArray[] $skyLightArrays */
@ -90,7 +93,7 @@ class LightPopulationTask extends AsyncTask{
/** /**
* @var \Closure * @var \Closure
* @phpstan-var \Closure(array<int, LightArray> $blockLight, array<int, LightArray> $skyLight, array<int, int> $heightMap) : void * @phpstan-var \Closure(array<int, LightArray> $blockLight, array<int, LightArray> $skyLight, non-empty-list<int> $heightMap) : void
*/ */
$callback = $this->fetchLocal(self::TLS_KEY_COMPLETION_CALLBACK); $callback = $this->fetchLocal(self::TLS_KEY_COMPLETION_CALLBACK);
$callback($blockLightArrays, $skyLightArrays, $heightMapArray); $callback($blockLightArrays, $skyLightArrays, $heightMapArray);

View File

@ -791,7 +791,7 @@ parameters:
path: ../../../src/utils/Config.php path: ../../../src/utils/Config.php
- -
message: "#^Parameter \\#1 \\$config of static method pocketmine\\\\utils\\\\Config\\:\\:writeProperties\\(\\) expects array\\<string, bool\\|float\\|int\\|string\\>, array\\<string, mixed\\> given\\.$#" message: "#^Parameter \\#1 \\$config of static method pocketmine\\\\utils\\\\Config\\:\\:writeProperties\\(\\) expects array\\<int\\|string, bool\\|float\\|int\\|string\\>, array\\<int\\|string, mixed\\> given\\.$#"
count: 1 count: 1
path: ../../../src/utils/Config.php path: ../../../src/utils/Config.php

View File

@ -1,20 +1,5 @@
parameters: parameters:
ignoreErrors: 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\\.$#" message: "#^Method pocketmine\\\\block\\\\DoubleTallGrass\\:\\:traitGetDropsForIncompatibleTool\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1 count: 1

View File

@ -16,7 +16,7 @@ parameters:
path: ../../../src/world/format/Chunk.php path: ../../../src/world/format/Chunk.php
- -
message: "#^Method pocketmine\\\\world\\\\format\\\\HeightArray\\:\\:getValues\\(\\) should return array\\<int, int\\> but returns array\\<int, int\\|null\\>\\.$#" message: "#^Method pocketmine\\\\world\\\\format\\\\HeightArray\\:\\:getValues\\(\\) should return non\\-empty\\-array\\<int, int\\> but returns array\\<int, int\\|null\\>\\.$#"
count: 1 count: 1
path: ../../../src/world/format/HeightArray.php path: ../../../src/world/format/HeightArray.php

View File

@ -35,8 +35,12 @@ class BlockTypeIdsTest extends TestCase{
$constants = $reflect->getConstants(); $constants = $reflect->getConstants();
unset($constants['FIRST_UNUSED_BLOCK_ID']); 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{ public function testNoDuplicates() : void{

View File

@ -35,8 +35,12 @@ class ItemTypeIdsTest extends TestCase{
$constants = $reflect->getConstants(); $constants = $reflect->getConstants();
unset($constants['FIRST_UNUSED_ITEM_ID']); 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{ public function testNoDuplicates() : void{