diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 5e21170bf..7e7268a04 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -54,13 +54,9 @@ class Anvil extends McRegion{ if($subChunk->isEmpty()){ continue; } - $nbt->Sections[++$subChunks] = new CompoundTag("", [ - new ByteTag("Y", $y), - new ByteArrayTag("Blocks", ChunkUtils::reorderByteArray($subChunk->getBlockIdArray())), //Generic in-memory chunks are currently always XZY - new ByteArrayTag("Data", ChunkUtils::reorderNibbleArray($subChunk->getBlockDataArray())), - new ByteArrayTag("SkyLight", ChunkUtils::reorderNibbleArray($subChunk->getBlockSkyLightArray(), "\xff")), - new ByteArrayTag("BlockLight", ChunkUtils::reorderNibbleArray($subChunk->getBlockLightArray())) - ]); + $tag = $this->serializeSubChunk($subChunk); + $tag->setByte("Y", $y); + $nbt->Sections[++$subChunks] = $tag; } $nbt->Biomes = new ByteArrayTag("Biomes", $chunk->getBiomeIdArray()); @@ -94,6 +90,15 @@ class Anvil extends McRegion{ return $writer->writeCompressed(ZLIB_ENCODING_DEFLATE, RegionLoader::$COMPRESSION_LEVEL); } + protected function serializeSubChunk(SubChunk $subChunk) : CompoundTag{ + return new CompoundTag("", [ + new ByteArrayTag("Blocks", ChunkUtils::reorderByteArray($subChunk->getBlockIdArray())), //Generic in-memory chunks are currently always XZY + new ByteArrayTag("Data", ChunkUtils::reorderNibbleArray($subChunk->getBlockDataArray())), + new ByteArrayTag("SkyLight", ChunkUtils::reorderNibbleArray($subChunk->getBlockSkyLightArray(), "\xff")), + new ByteArrayTag("BlockLight", ChunkUtils::reorderNibbleArray($subChunk->getBlockLightArray())) + ]); + } + public function nbtDeserialize(string $data){ $nbt = new NBT(NBT::BIG_ENDIAN); try{ @@ -111,12 +116,7 @@ class Anvil extends McRegion{ if($chunk->Sections instanceof ListTag){ foreach($chunk->Sections as $subChunk){ if($subChunk instanceof CompoundTag){ - $subChunks[$subChunk->Y->getValue()] = new SubChunk( - ChunkUtils::reorderByteArray($subChunk->Blocks->getValue()), - ChunkUtils::reorderNibbleArray($subChunk->Data->getValue()), - ChunkUtils::reorderNibbleArray($subChunk->SkyLight->getValue(), "\xff"), - ChunkUtils::reorderNibbleArray($subChunk->BlockLight->getValue()) - ); + $subChunks[$subChunk->Y->getValue()] = $this->deserializeSubChunk($subChunk); } } } @@ -148,6 +148,15 @@ class Anvil extends McRegion{ } } + protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{ + return new SubChunk( + ChunkUtils::reorderByteArray($subChunk->Blocks->getValue()), + ChunkUtils::reorderNibbleArray($subChunk->Data->getValue()), + ChunkUtils::reorderNibbleArray($subChunk->SkyLight->getValue(), "\xff"), + ChunkUtils::reorderNibbleArray($subChunk->BlockLight->getValue()) + ); + } + public static function getProviderName() : string{ return "anvil"; } diff --git a/src/pocketmine/level/format/io/region/PMAnvil.php b/src/pocketmine/level/format/io/region/PMAnvil.php index 10e436ae2..6e7cef20d 100644 --- a/src/pocketmine/level/format/io/region/PMAnvil.php +++ b/src/pocketmine/level/format/io/region/PMAnvil.php @@ -40,108 +40,22 @@ class PMAnvil extends Anvil{ const REGION_FILE_EXTENSION = "mcapm"; - public function nbtSerialize(Chunk $chunk) : string{ - $nbt = new CompoundTag("Level", []); - $nbt->xPos = new IntTag("xPos", $chunk->getX()); - $nbt->zPos = new IntTag("zPos", $chunk->getZ()); - - $nbt->V = new ByteTag("V", 1); - $nbt->LastUpdate = new LongTag("LastUpdate", 0); //TODO - $nbt->InhabitedTime = new LongTag("InhabitedTime", 0); //TODO - $nbt->TerrainPopulated = new ByteTag("TerrainPopulated", $chunk->isPopulated() ? 1 : 0); - $nbt->LightPopulated = new ByteTag("LightPopulated", $chunk->isLightPopulated() ? 1 : 0); - - $nbt->Sections = new ListTag("Sections", [], NBT::TAG_Compound); - - $subChunks = -1; - foreach($chunk->getSubChunks() as $y => $subChunk){ - if($subChunk->isEmpty()){ - continue; - } - $nbt->Sections[++$subChunks] = new CompoundTag("", [ - new ByteTag("Y", $y), - new ByteArrayTag("Blocks", $subChunk->getBlockIdArray()), - new ByteArrayTag("Data", $subChunk->getBlockDataArray()), - new ByteArrayTag("SkyLight", $subChunk->getBlockSkyLightArray()), - new ByteArrayTag("BlockLight", $subChunk->getBlockLightArray()) - ]); - } - - $nbt->Biomes = new ByteArrayTag("Biomes", $chunk->getBiomeIdArray()); - $nbt->HeightMap = new IntArrayTag("HeightMap", $chunk->getHeightMapArray()); - - $entities = []; - - foreach($chunk->getEntities() as $entity){ - if($entity->canSaveWithChunk() and !$entity->isClosed()){ - $entity->saveNBT(); - $entities[] = $entity->namedtag; - } - } - - $nbt->Entities = new ListTag("Entities", $entities, NBT::TAG_Compound); - - $tiles = []; - foreach($chunk->getTiles() as $tile){ - $tile->saveNBT(); - $tiles[] = $tile->namedtag; - } - - $nbt->TileEntities = new ListTag("TileEntities", $tiles, NBT::TAG_Compound); - - //TODO: TileTicks - - $writer = new NBT(NBT::BIG_ENDIAN); - $nbt->setName("Level"); - $writer->setData(new CompoundTag("", [$nbt])); - - return $writer->writeCompressed(ZLIB_ENCODING_DEFLATE, RegionLoader::$COMPRESSION_LEVEL); + protected function serializeSubChunk(SubChunk $subChunk) : CompoundTag{ + return new CompoundTag("", [ + new ByteArrayTag("Blocks", $subChunk->getBlockIdArray()), + new ByteArrayTag("Data", $subChunk->getBlockDataArray()), + new ByteArrayTag("SkyLight", $subChunk->getBlockSkyLightArray()), + new ByteArrayTag("BlockLight", $subChunk->getBlockLightArray()) + ]); } - public function nbtDeserialize(string $data){ - $nbt = new NBT(NBT::BIG_ENDIAN); - try{ - $nbt->readCompressed($data); - - $chunk = $nbt->getData(); - - if(!isset($chunk->Level) or !($chunk->Level instanceof CompoundTag)){ - throw new ChunkException("Invalid NBT format"); - } - - $chunk = $chunk->Level; - - $subChunks = []; - if($chunk->Sections instanceof ListTag){ - foreach($chunk->Sections as $subChunk){ - if($subChunk instanceof CompoundTag){ - $subChunks[$subChunk->Y->getValue()] = new SubChunk( - $subChunk->Blocks->getValue(), - $subChunk->Data->getValue(), - $subChunk->SkyLight->getValue(), - $subChunk->BlockLight->getValue() - ); - } - } - } - - $result = new Chunk( - $chunk["xPos"], - $chunk["zPos"], - $subChunks, - isset($chunk->Entities) ? $chunk->Entities->getValue() : [], - isset($chunk->TileEntities) ? $chunk->TileEntities->getValue() : [], - isset($chunk->Biomes) ? $chunk->Biomes->getValue() : "", - isset($chunk->HeightMap) ? $chunk->HeightMap->getValue() : [] - ); - $result->setLightPopulated(isset($chunk->LightPopulated) ? ((bool) $chunk->LightPopulated->getValue()) : false); - $result->setPopulated(isset($chunk->TerrainPopulated) ? ((bool) $chunk->TerrainPopulated->getValue()) : false); - $result->setGenerated(true); - return $result; - }catch(\Throwable $e){ - MainLogger::getLogger()->logException($e); - return null; - } + protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{ + return new SubChunk( + $subChunk->Blocks->getValue(), + $subChunk->Data->getValue(), + $subChunk->SkyLight->getValue(), + $subChunk->BlockLight->getValue() + ); } public static function getProviderName() : string{