Further cleanup on NBT dynamic field access

not sure how I missed so many of these... there are probably lots more besides :(
This commit is contained in:
Dylan K. Taylor 2017-11-17 11:19:36 +00:00
parent 48a7627b96
commit 665130561e
3 changed files with 32 additions and 32 deletions

View File

@ -73,8 +73,11 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
protected $baseOffset = 1.62; protected $baseOffset = 1.62;
public function __construct(Level $level, CompoundTag $nbt){ 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()))){ if($this->skin === null){
throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set"); $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); parent::__construct($level, $nbt);

View File

@ -30,6 +30,7 @@ use pocketmine\block\BlockFactory;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\level\Level; use pocketmine\level\Level;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player; use pocketmine\Player;
use pocketmine\tile\Spawnable; use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile; use pocketmine\tile\Tile;
@ -729,7 +730,7 @@ class Chunk{
$level->timings->syncChunkLoadEntitiesTimer->startTiming(); $level->timings->syncChunkLoadEntitiesTimer->startTiming();
foreach($this->NBTentities as $nbt){ foreach($this->NBTentities as $nbt){
if($nbt instanceof CompoundTag){ if($nbt instanceof CompoundTag){
if(!isset($nbt->id)){ if(!$nbt->hasTag("id")){ //allow mixed types (because of leveldb)
$changed = true; $changed = true;
continue; continue;
} }
@ -740,7 +741,7 @@ class Chunk{
} }
try{ try{
$entity = Entity::createEntity($nbt["id"], $level, $nbt); $entity = Entity::createEntity($nbt->getTag("id")->getValue(), $level, $nbt);
if(!($entity instanceof Entity)){ if(!($entity instanceof Entity)){
$changed = true; $changed = true;
continue; continue;
@ -757,17 +758,17 @@ class Chunk{
$level->timings->syncChunkLoadTileEntitiesTimer->startTiming(); $level->timings->syncChunkLoadTileEntitiesTimer->startTiming();
foreach($this->NBTtiles as $nbt){ foreach($this->NBTtiles as $nbt){
if($nbt instanceof CompoundTag){ if($nbt instanceof CompoundTag){
if(!isset($nbt->id)){ if(!$nbt->hasTag(Tile::TAG_ID, StringTag::class)){
$changed = true; $changed = true;
continue; 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; $changed = true;
continue; //Fixes tiles allocated in wrong chunks. 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; $changed = true;
continue; continue;
} }

View File

@ -121,19 +121,17 @@ class McRegion extends BaseLevelProvider{
try{ try{
$nbt->readCompressed($data); $nbt->readCompressed($data);
$chunk = $nbt->getData(); $chunk = $nbt->getData()->getCompoundTag("Level");
if(!isset($chunk->Level) or !($chunk->Level instanceof CompoundTag)){ if($chunk === null){
throw new ChunkException("Invalid NBT format"); throw new ChunkException("Invalid NBT format, 'Level' key not found");
} }
$chunk = $chunk->Level;
$subChunks = []; $subChunks = [];
$fullIds = isset($chunk->Blocks) ? $chunk->Blocks->getValue() : str_repeat("\x00", 32768); $fullIds = $chunk->hasTag("Blocks", ByteArrayTag::class) ? $chunk->getByteArray("Blocks") : str_repeat("\x00", 32768);
$fullData = isset($chunk->Data) ? $chunk->Data->getValue() : str_repeat("\x00", 16384); $fullData = $chunk->hasTag("Data", ByteArrayTag::class) ? $chunk->getByteArray("Data") : str_repeat("\x00", 16384);
$fullSkyLight = isset($chunk->SkyLight) ? $chunk->SkyLight->getValue() : str_repeat("\xff", 16384); $fullSkyLight = $chunk->hasTag("SkyLight", ByteArrayTag::class) ? $chunk->getByteArray("SkyLight") : str_repeat("\xff", 16384);
$fullBlockLight = isset($chunk->BlockLight) ? $chunk->BlockLight->getValue() : str_repeat("\x00", 16384); $fullBlockLight = $chunk->hasTag("BlockLight", ByteArrayTag::class) ? $chunk->getByteArray("BlockLight") : str_repeat("\x00", 16384);
for($y = 0; $y < 8; ++$y){ for($y = 0; $y < 8; ++$y){
$offset = ($y << 4); $offset = ($y << 4);
@ -163,34 +161,32 @@ class McRegion extends BaseLevelProvider{
$subChunks[$y] = new SubChunk($ids, $data, $skyLight, $blockLight); $subChunks[$y] = new SubChunk($ids, $data, $skyLight, $blockLight);
} }
if(isset($chunk->BiomeColors)){ if($chunk->hasTag("BiomeColors", IntArrayTag::class)){
$biomeIds = ChunkUtils::convertBiomeColors($chunk->BiomeColors->getValue()); //Convert back to original format $biomeIds = ChunkUtils::convertBiomeColors($chunk->getIntArray("BiomeColors")); //Convert back to original format
}elseif(isset($chunk->Biomes)){ }elseif($chunk->hasTag("Biomes", ByteArrayTag::class)){
$biomeIds = $chunk->Biomes->getValue(); $biomeIds = $chunk->getByteArray("Biomes");
}else{ }else{
$biomeIds = ""; $biomeIds = "";
} }
$heightMap = []; $heightMap = [];
if(isset($chunk->HeightMap)){ if($chunk->hasTag("HeightMap", ByteArrayTag::class)){
if($chunk->HeightMap instanceof ByteArrayTag){ $heightMap = array_values(unpack("C*", $chunk->getByteArray("HeightMap")));
$heightMap = array_values(unpack("C*", $chunk->HeightMap->getValue())); }elseif($chunk->hasTag("HeightMap", IntArrayTag::class)){
}elseif($chunk->HeightMap instanceof IntArrayTag){ $heightMap = $chunk->getIntArray("HeightMap"); #blameshoghicp
$heightMap = $chunk->HeightMap->getValue(); #blameshoghicp
}
} }
$result = new Chunk( $result = new Chunk(
$chunk["xPos"], $chunk->getInt("xPos"),
$chunk["zPos"], $chunk->getInt("zPos"),
$subChunks, $subChunks,
isset($chunk->Entities) ? $chunk->Entities->getValue() : [], $chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [],
isset($chunk->TileEntities) ? $chunk->TileEntities->getValue() : [], $chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [],
$biomeIds, $biomeIds,
$heightMap $heightMap
); );
$result->setLightPopulated(isset($chunk->LightPopulated) ? ((bool) $chunk->LightPopulated->getValue()) : false); $result->setLightPopulated($chunk->getByte("LightPopulated", 0) !== 0);
$result->setPopulated(isset($chunk->TerrainPopulated) ? ((bool) $chunk->TerrainPopulated->getValue()) : false); $result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0);
$result->setGenerated(true); $result->setGenerated(true);
return $result; return $result;
}catch(\Throwable $e){ }catch(\Throwable $e){