diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 04a8c943a..103116947 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -73,8 +73,11 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ protected $baseOffset = 1.62; public function __construct(Level $level, CompoundTag $nbt){ - if($this->skin === null and (!isset($nbt->Skin) or !isset($nbt->Skin->Data) or !Player::isValidSkin($nbt->Skin->Data->getValue()))){ - throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set"); + if($this->skin === null){ + $skinTag = $nbt->getCompoundTag("Skin"); + if($skinTag === null or !self::isValidSkin($skinTag->getString("Data", "", true))){ + throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set"); + } } parent::__construct($level, $nbt); diff --git a/src/pocketmine/level/format/Chunk.php b/src/pocketmine/level/format/Chunk.php index 74f5b5d66..da04e38ea 100644 --- a/src/pocketmine/level/format/Chunk.php +++ b/src/pocketmine/level/format/Chunk.php @@ -30,6 +30,7 @@ use pocketmine\block\BlockFactory; use pocketmine\entity\Entity; use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\StringTag; use pocketmine\Player; use pocketmine\tile\Spawnable; use pocketmine\tile\Tile; @@ -729,7 +730,7 @@ class Chunk{ $level->timings->syncChunkLoadEntitiesTimer->startTiming(); foreach($this->NBTentities as $nbt){ if($nbt instanceof CompoundTag){ - if(!isset($nbt->id)){ + if(!$nbt->hasTag("id")){ //allow mixed types (because of leveldb) $changed = true; continue; } @@ -740,7 +741,7 @@ class Chunk{ } try{ - $entity = Entity::createEntity($nbt["id"], $level, $nbt); + $entity = Entity::createEntity($nbt->getTag("id")->getValue(), $level, $nbt); if(!($entity instanceof Entity)){ $changed = true; continue; @@ -757,17 +758,17 @@ class Chunk{ $level->timings->syncChunkLoadTileEntitiesTimer->startTiming(); foreach($this->NBTtiles as $nbt){ if($nbt instanceof CompoundTag){ - if(!isset($nbt->id)){ + if(!$nbt->hasTag(Tile::TAG_ID, StringTag::class)){ $changed = true; continue; } - if(($nbt["x"] >> 4) !== $this->x or ($nbt["z"] >> 4) !== $this->z){ + if(($nbt->getInt(Tile::TAG_X) >> 4) !== $this->x or ($nbt->getInt(Tile::TAG_Z) >> 4) !== $this->z){ $changed = true; continue; //Fixes tiles allocated in wrong chunks. } - if(Tile::createTile($nbt["id"], $level, $nbt) === null){ + if(Tile::createTile($nbt->getString(Tile::TAG_ID), $level, $nbt) === null){ $changed = true; continue; } diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index c5dd16505..8f6f5d22a 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -121,19 +121,17 @@ class McRegion extends BaseLevelProvider{ try{ $nbt->readCompressed($data); - $chunk = $nbt->getData(); + $chunk = $nbt->getData()->getCompoundTag("Level"); - if(!isset($chunk->Level) or !($chunk->Level instanceof CompoundTag)){ - throw new ChunkException("Invalid NBT format"); + if($chunk === null){ + throw new ChunkException("Invalid NBT format, 'Level' key not found"); } - $chunk = $chunk->Level; - $subChunks = []; - $fullIds = isset($chunk->Blocks) ? $chunk->Blocks->getValue() : str_repeat("\x00", 32768); - $fullData = isset($chunk->Data) ? $chunk->Data->getValue() : str_repeat("\x00", 16384); - $fullSkyLight = isset($chunk->SkyLight) ? $chunk->SkyLight->getValue() : str_repeat("\xff", 16384); - $fullBlockLight = isset($chunk->BlockLight) ? $chunk->BlockLight->getValue() : str_repeat("\x00", 16384); + $fullIds = $chunk->hasTag("Blocks", ByteArrayTag::class) ? $chunk->getByteArray("Blocks") : str_repeat("\x00", 32768); + $fullData = $chunk->hasTag("Data", ByteArrayTag::class) ? $chunk->getByteArray("Data") : str_repeat("\x00", 16384); + $fullSkyLight = $chunk->hasTag("SkyLight", ByteArrayTag::class) ? $chunk->getByteArray("SkyLight") : str_repeat("\xff", 16384); + $fullBlockLight = $chunk->hasTag("BlockLight", ByteArrayTag::class) ? $chunk->getByteArray("BlockLight") : str_repeat("\x00", 16384); for($y = 0; $y < 8; ++$y){ $offset = ($y << 4); @@ -163,34 +161,32 @@ class McRegion extends BaseLevelProvider{ $subChunks[$y] = new SubChunk($ids, $data, $skyLight, $blockLight); } - if(isset($chunk->BiomeColors)){ - $biomeIds = ChunkUtils::convertBiomeColors($chunk->BiomeColors->getValue()); //Convert back to original format - }elseif(isset($chunk->Biomes)){ - $biomeIds = $chunk->Biomes->getValue(); + if($chunk->hasTag("BiomeColors", IntArrayTag::class)){ + $biomeIds = ChunkUtils::convertBiomeColors($chunk->getIntArray("BiomeColors")); //Convert back to original format + }elseif($chunk->hasTag("Biomes", ByteArrayTag::class)){ + $biomeIds = $chunk->getByteArray("Biomes"); }else{ $biomeIds = ""; } $heightMap = []; - if(isset($chunk->HeightMap)){ - if($chunk->HeightMap instanceof ByteArrayTag){ - $heightMap = array_values(unpack("C*", $chunk->HeightMap->getValue())); - }elseif($chunk->HeightMap instanceof IntArrayTag){ - $heightMap = $chunk->HeightMap->getValue(); #blameshoghicp - } + if($chunk->hasTag("HeightMap", ByteArrayTag::class)){ + $heightMap = array_values(unpack("C*", $chunk->getByteArray("HeightMap"))); + }elseif($chunk->hasTag("HeightMap", IntArrayTag::class)){ + $heightMap = $chunk->getIntArray("HeightMap"); #blameshoghicp } $result = new Chunk( - $chunk["xPos"], - $chunk["zPos"], + $chunk->getInt("xPos"), + $chunk->getInt("zPos"), $subChunks, - isset($chunk->Entities) ? $chunk->Entities->getValue() : [], - isset($chunk->TileEntities) ? $chunk->TileEntities->getValue() : [], + $chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [], + $chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [], $biomeIds, $heightMap ); - $result->setLightPopulated(isset($chunk->LightPopulated) ? ((bool) $chunk->LightPopulated->getValue()) : false); - $result->setPopulated(isset($chunk->TerrainPopulated) ? ((bool) $chunk->TerrainPopulated->getValue()) : false); + $result->setLightPopulated($chunk->getByte("LightPopulated", 0) !== 0); + $result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0); $result->setGenerated(true); return $result; }catch(\Throwable $e){