Merge branch 'stable' into next-minor

This commit is contained in:
Dylan K. Taylor
2019-12-12 18:29:04 +00:00
13 changed files with 87 additions and 48 deletions

View File

@ -8,7 +8,7 @@ includes:
- tests/phpstan/configs/runtime-type-checks.neon - tests/phpstan/configs/runtime-type-checks.neon
parameters: parameters:
level: 4 level: 5
autoload_files: autoload_files:
- tests/phpstan/bootstrap.php - tests/phpstan/bootstrap.php
- src/pocketmine/PocketMine.php - src/pocketmine/PocketMine.php

View File

@ -2247,6 +2247,9 @@ class Server{
$this->crashDump(); $this->crashDump();
} }
/**
* @return void
*/
public function crashDump(){ public function crashDump(){
while(@ob_end_flush()){} while(@ob_end_flush()){}
if(!$this->isRunning){ if(!$this->isRunning){

View File

@ -84,6 +84,9 @@ class EnderChest extends Chest{
$enderChest = $t; $enderChest = $t;
}else{ }else{
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this)); $enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this));
if(!($enderChest instanceof TileEnderChest)){
return true;
}
} }
if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){ if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){

View File

@ -463,12 +463,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/** @var Block[]|null */ /** @var Block[]|null */
protected $blocksAround = null; protected $blocksAround = null;
/** @var float|null */ /** @var float */
public $lastX = null; public $lastX;
/** @var float|null */ /** @var float */
public $lastY = null; public $lastY;
/** @var float|null */ /** @var float */
public $lastZ = null; public $lastZ;
/** @var Vector3 */ /** @var Vector3 */
protected $motion; protected $motion;

View File

@ -66,19 +66,23 @@ class PlayerInventory extends BaseInventory{
* @return bool if the equipment change was successful, false if not. * @return bool if the equipment change was successful, false if not.
*/ */
public function equipItem(int $hotbarSlot) : bool{ public function equipItem(int $hotbarSlot) : bool{
$holder = $this->getHolder();
if(!$this->isHotbarSlot($hotbarSlot)){ if(!$this->isHotbarSlot($hotbarSlot)){
$this->sendContents($this->getHolder()); if($holder instanceof Player){
$this->sendContents($holder);
}
return false; return false;
} }
$ev = new PlayerItemHeldEvent($this->getHolder(), $this->getItem($hotbarSlot), $hotbarSlot); if($holder instanceof Player){
$ev->call(); $ev = new PlayerItemHeldEvent($holder, $this->getItem($hotbarSlot), $hotbarSlot);
$ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){
$this->sendHeldItem($this->getHolder()); $this->sendHeldItem($holder);
return false; return false;
}
} }
$this->setHeldItemIndex($hotbarSlot, false); $this->setHeldItemIndex($hotbarSlot, false);
return true; return true;

View File

@ -115,9 +115,9 @@ class BaseLang{
} }
/** /**
* @param string $str * @param string $str
* @param string[] $params * @param (float|int|string)[] $params
* @param string|null $onlyPrefix * @param string|null $onlyPrefix
* *
* @return string * @return string
*/ */

View File

@ -31,8 +31,8 @@ class TranslationContainer extends TextContainer{
protected $params = []; protected $params = [];
/** /**
* @param string $text * @param string $text
* @param string[] $params * @param (float|int|string)[] $params
*/ */
public function __construct(string $text, array $params = []){ public function __construct(string $text, array $params = []){
parent::__construct($text); parent::__construct($text);

View File

@ -33,12 +33,12 @@ class Location extends Position{
public $pitch; public $pitch;
/** /**
* @param int $x * @param float|int $x
* @param int $y * @param float|int $y
* @param int $z * @param float|int $z
* @param float $yaw * @param float $yaw
* @param float $pitch * @param float $pitch
* @param Level $level * @param Level $level
*/ */
public function __construct($x = 0, $y = 0, $z = 0, $yaw = 0.0, $pitch = 0.0, Level $level = null){ public function __construct($x = 0, $y = 0, $z = 0, $yaw = 0.0, $pitch = 0.0, Level $level = null){
$this->yaw = $yaw; $this->yaw = $yaw;

View File

@ -33,10 +33,10 @@ class Position extends Vector3{
public $level = null; public $level = null;
/** /**
* @param int $x * @param float|int $x
* @param int $y * @param float|int $y
* @param int $z * @param float|int $z
* @param Level $level * @param Level $level
*/ */
public function __construct($x = 0, $y = 0, $z = 0, Level $level = null){ public function __construct($x = 0, $y = 0, $z = 0, Level $level = null){
parent::__construct($x, $y, $z); parent::__construct($x, $y, $z);

View File

@ -26,6 +26,7 @@ namespace pocketmine\level\format\io\leveldb;
use pocketmine\level\format\Chunk; use pocketmine\level\format\Chunk;
use pocketmine\level\format\io\BaseLevelProvider; use pocketmine\level\format\io\BaseLevelProvider;
use pocketmine\level\format\io\ChunkUtils; use pocketmine\level\format\io\ChunkUtils;
use pocketmine\level\format\io\exception\CorruptedChunkException;
use pocketmine\level\format\io\exception\UnsupportedChunkFormatException; use pocketmine\level\format\io\exception\UnsupportedChunkFormatException;
use pocketmine\level\format\SubChunk; use pocketmine\level\format\SubChunk;
use pocketmine\level\generator\Flat; use pocketmine\level\generator\Flat;
@ -414,24 +415,27 @@ class LevelDB extends BaseLevelProvider{
/** @var CompoundTag[] $entities */ /** @var CompoundTag[] $entities */
$entities = []; $entities = [];
if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and $entityData !== ""){ if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and $entityData !== ""){
$entities = $nbt->read($entityData, true); $entityTags = $nbt->read($entityData, true);
if(!is_array($entities)){ foreach((is_array($entityTags) ? $entityTags : [$entityTags]) as $entityTag){
$entities = [$entities]; if(!($entityTag instanceof CompoundTag)){
} throw new CorruptedChunkException("Entity root tag should be TAG_Compound");
} }
if($entityTag->hasTag("id", IntTag::class)){
/** @var CompoundTag $entityNBT */ $entityTag->setInt("id", $entityTag->getInt("id") & 0xff); //remove type flags - TODO: use these instead of removing them)
foreach($entities as $entityNBT){ }
if($entityNBT->hasTag("id", IntTag::class)){ $entities[] = $entityTag;
$entityNBT->setInt("id", $entityNBT->getInt("id") & 0xff); //remove type flags - TODO: use these instead of removing them)
} }
} }
/** @var CompoundTag[] $tiles */
$tiles = []; $tiles = [];
if(($tileData = $this->db->get($index . self::TAG_BLOCK_ENTITY)) !== false and $tileData !== ""){ if(($tileData = $this->db->get($index . self::TAG_BLOCK_ENTITY)) !== false and $tileData !== ""){
$tiles = $nbt->read($tileData, true); $tileTags = $nbt->read($tileData, true);
if(!is_array($tiles)){ foreach((is_array($tileTags) ? $tileTags : [$tileTags]) as $tileTag){
$tiles = [$tiles]; if(!($tileTag instanceof CompoundTag)){
throw new CorruptedChunkException("Tile root tag should be TAG_Compound");
}
$tiles[] = $tileTag;
} }
} }

View File

@ -51,7 +51,7 @@ class Anvil extends McRegion{
$subChunks = []; $subChunks = [];
foreach($chunk->getSubChunks() as $y => $subChunk){ foreach($chunk->getSubChunks() as $y => $subChunk){
if($subChunk->isEmpty()){ if(!($subChunk instanceof SubChunk) or $subChunk->isEmpty()){
continue; continue;
} }
@ -122,8 +122,8 @@ class Anvil extends McRegion{
$chunk->getInt("xPos"), $chunk->getInt("xPos"),
$chunk->getInt("zPos"), $chunk->getInt("zPos"),
$subChunks, $subChunks,
$chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [], $chunk->hasTag("Entities", ListTag::class) ? self::getCompoundList("Entities", $chunk->getListTag("Entities")) : [],
$chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [], $chunk->hasTag("TileEntities", ListTag::class) ? self::getCompoundList("TileEntities", $chunk->getListTag("TileEntities")) : [],
$biomeIds, $biomeIds,
$chunk->getIntArray("HeightMap", []) $chunk->getIntArray("HeightMap", [])
); );

View File

@ -194,8 +194,8 @@ class McRegion extends BaseLevelProvider{
$chunk->getInt("xPos"), $chunk->getInt("xPos"),
$chunk->getInt("zPos"), $chunk->getInt("zPos"),
$subChunks, $subChunks,
$chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [], $chunk->hasTag("Entities", ListTag::class) ? self::getCompoundList("Entities", $chunk->getListTag("Entities")) : [],
$chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [], $chunk->hasTag("TileEntities", ListTag::class) ? self::getCompoundList("TileEntities", $chunk->getListTag("TileEntities")) : [],
$biomeIds, $biomeIds,
$heightMap $heightMap
); );
@ -205,6 +205,31 @@ class McRegion extends BaseLevelProvider{
return $result; return $result;
} }
/**
* @param string $context
* @param ListTag $list
*
* @return CompoundTag[]
* @throws CorruptedChunkException
*/
protected static function getCompoundList(string $context, ListTag $list) : array{
if($list->count() === 0){ //empty lists might have wrong types, we don't care
return [];
}
if($list->getTagType() !== NBT::TAG_Compound){
throw new CorruptedChunkException("Expected TAG_List<TAG_Compound> for '$context'");
}
$result = [];
foreach($list as $tag){
if(!($tag instanceof CompoundTag)){
//this should never happen, but it's still possible due to lack of native type safety
throw new CorruptedChunkException("Expected TAG_List<TAG_Compound> for '$context'");
}
$result[] = $tag;
}
return $result;
}
public static function getProviderName() : string{ public static function getProviderName() : string{
return "mcregion"; return "mcregion";
} }

View File

@ -35,7 +35,7 @@ class CompressBatchedTask extends AsyncTask{
/** /**
* @param BatchPacket $batch * @param BatchPacket $batch
* @param string[] $targets * @param Player[] $targets
*/ */
public function __construct(BatchPacket $batch, array $targets){ public function __construct(BatchPacket $batch, array $targets){
$this->data = $batch->payload; $this->data = $batch->payload;