PocketMine-MP 5.21.2 git-b2aa6396c3cc2cafdd815eacc360e1ad89599899
Loading...
Searching...
No Matches
LegacyAnvilChunkTrait.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\world\format\io\region;
25
39use pocketmine\world\format\PalettedBlockArray;
41use function strlen;
42use function zlib_decode;
43
53trait LegacyAnvilChunkTrait{
57 protected function deserializeChunk(string $data, \Logger $logger) : ?LoadedChunkData{
58 $decompressed = @zlib_decode($data);
59 if($decompressed === false){
60 throw new CorruptedChunkException("Failed to decompress chunk NBT");
61 }
62 $nbt = new BigEndianNbtSerializer();
63 try{
64 $chunk = $nbt->read($decompressed)->mustGetCompoundTag();
65 }catch(NbtDataException $e){
66 throw new CorruptedChunkException($e->getMessage(), 0, $e);
67 }
68 $chunk = $chunk->getTag("Level");
69 if(!($chunk instanceof CompoundTag)){
70 throw new CorruptedChunkException("'Level' key is missing from chunk NBT");
71 }
72
73 $makeBiomeArray = function(string $biomeIds) : PalettedBlockArray{
74 if(strlen($biomeIds) !== 256){
75 throw new CorruptedChunkException("Expected biome array to be exactly 256 bytes, got " . strlen($biomeIds));
76 }
77 //TODO: we may need to convert legacy biome IDs
78 return ChunkUtils::extrapolate3DBiomes($biomeIds);
79 };
80
81 if(($biomeColorsTag = $chunk->getTag("BiomeColors")) instanceof IntArrayTag){
82 $biomes3d = $makeBiomeArray(ChunkUtils::convertBiomeColors($biomeColorsTag->getValue())); //Convert back to original format
83 }elseif(($biomesTag = $chunk->getTag("Biomes")) instanceof ByteArrayTag){
84 $biomes3d = $makeBiomeArray($biomesTag->getValue());
85 }else{
86 $biomes3d = new PalettedBlockArray(BiomeIds::OCEAN);
87 }
88
89 $subChunks = [];
90 $subChunksTag = $chunk->getListTag("Sections") ?? [];
91 foreach($subChunksTag as $subChunk){
92 if($subChunk instanceof CompoundTag){
93 $y = $subChunk->getByte("Y");
94 $subChunks[$y] = $this->deserializeSubChunk($subChunk, clone $biomes3d, new \PrefixedLogger($logger, "Subchunk y=$y"));
95 }
96 }
97 for($y = Chunk::MIN_SUBCHUNK_INDEX; $y <= Chunk::MAX_SUBCHUNK_INDEX; ++$y){
98 if(!isset($subChunks[$y])){
99 $subChunks[$y] = new SubChunk(Block::EMPTY_STATE_ID, [], clone $biomes3d);
100 }
101 }
102
103 return new LoadedChunkData(
104 data: new ChunkData(
105 $subChunks,
106 $chunk->getByte("TerrainPopulated", 0) !== 0,
107 ($entitiesTag = $chunk->getTag("Entities")) instanceof ListTag ? self::getCompoundList("Entities", $entitiesTag) : [],
108 ($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [],
109 ),
110 upgraded: true,
111 fixerFlags: LoadedChunkData::FIXER_FLAG_ALL
112 );
113 }
114
115 abstract protected function deserializeSubChunk(CompoundTag $subChunk, PalettedBlockArray $biomes3d, \Logger $logger) : SubChunk;
116
117}
static extrapolate3DBiomes(string $biomes2d)
static convertBiomeColors(array $array)