First look at 3D biome support

This commit is contained in:
Dylan K. Taylor
2023-01-17 21:41:30 +00:00
parent 3a13f5cf5f
commit 7abfc46567
19 changed files with 319 additions and 243 deletions

View File

@@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\world\format\io\region;
use pocketmine\block\Block;
use pocketmine\block\BlockTypeIds;
use pocketmine\data\bedrock\BiomeIds;
use pocketmine\nbt\BigEndianNbtSerializer;
use pocketmine\nbt\NbtDataException;
@@ -30,12 +32,13 @@ use pocketmine\nbt\tag\ByteArrayTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntArrayTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\world\format\BiomeArray;
use pocketmine\world\format\Chunk;
use pocketmine\world\format\io\ChunkData;
use pocketmine\world\format\io\ChunkUtils;
use pocketmine\world\format\io\exception\CorruptedChunkException;
use pocketmine\world\format\PalettedBlockArray;
use pocketmine\world\format\SubChunk;
use function strlen;
use function zlib_decode;
/**
@@ -67,34 +70,38 @@ trait LegacyAnvilChunkTrait{
throw new CorruptedChunkException("'Level' key is missing from chunk NBT");
}
$makeBiomeArray = function(string $biomeIds) : PalettedBlockArray{
if(strlen($biomeIds) !== 256){
throw new CorruptedChunkException("Expected biome array to be exactly 256 bytes, got " . strlen($biomeIds));
}
//TODO: we may need to convert legacy biome IDs
return ChunkUtils::extrapolate3DBiomes($biomeIds);
};
if(($biomeColorsTag = $chunk->getTag("BiomeColors")) instanceof IntArrayTag){
$biomes3d = $makeBiomeArray(ChunkUtils::convertBiomeColors($biomeColorsTag->getValue())); //Convert back to original format
}elseif(($biomesTag = $chunk->getTag("Biomes")) instanceof ByteArrayTag){
$biomes3d = $makeBiomeArray($biomesTag->getValue());
}else{
$biomes3d = new PalettedBlockArray(BiomeIds::OCEAN);
}
$subChunks = [];
$subChunksTag = $chunk->getListTag("Sections") ?? [];
foreach($subChunksTag as $subChunk){
if($subChunk instanceof CompoundTag){
$subChunks[$subChunk->getByte("Y")] = $this->deserializeSubChunk($subChunk);
$subChunks[$subChunk->getByte("Y")] = $this->deserializeSubChunk($subChunk, clone $biomes3d);
}
}
$makeBiomeArray = function(string $biomeIds) : BiomeArray{
try{
return new BiomeArray($biomeIds);
}catch(\InvalidArgumentException $e){
throw new CorruptedChunkException($e->getMessage(), 0, $e);
for($y = Chunk::MIN_SUBCHUNK_INDEX; $y <= Chunk::MAX_SUBCHUNK_INDEX; ++$y){
if(!isset($subChunks[$y])){
$subChunks[$y] = new SubChunk(BlockTypeIds::AIR << Block::INTERNAL_STATE_DATA_BITS, [], clone $biomes3d);
}
};
$biomeArray = null;
if(($biomeColorsTag = $chunk->getTag("BiomeColors")) instanceof IntArrayTag){
$biomeArray = $makeBiomeArray(ChunkUtils::convertBiomeColors($biomeColorsTag->getValue())); //Convert back to original format
}elseif(($biomesTag = $chunk->getTag("Biomes")) instanceof ByteArrayTag){
$biomeArray = $makeBiomeArray($biomesTag->getValue());
}else{
$biomeArray = BiomeArray::fill(BiomeIds::OCEAN);
}
return new ChunkData(
new Chunk(
$subChunks,
$biomeArray,
$chunk->getByte("TerrainPopulated", 0) !== 0
),
($entitiesTag = $chunk->getTag("Entities")) instanceof ListTag ? self::getCompoundList("Entities", $entitiesTag) : [],
@@ -102,6 +109,6 @@ trait LegacyAnvilChunkTrait{
);
}
abstract protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk;
abstract protected function deserializeSubChunk(CompoundTag $subChunk, PalettedBlockArray $biomes3d) : SubChunk;
}