PocketMine-MP 5.18.1 git-9381fc4172e5dce4cada1cb356050c8a2ab57b94
McRegion.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
40use pocketmine\world\format\PalettedBlockArray;
42use function strlen;
43use function zlib_decode;
44
49 protected function deserializeChunk(string $data, \Logger $logger) : ?LoadedChunkData{
50 $decompressed = @zlib_decode($data);
51 if($decompressed === false){
52 throw new CorruptedChunkException("Failed to decompress chunk NBT");
53 }
54 $nbt = new BigEndianNbtSerializer();
55 try{
56 $chunk = $nbt->read($decompressed)->mustGetCompoundTag();
57 }catch(NbtDataException $e){
58 throw new CorruptedChunkException($e->getMessage(), 0, $e);
59 }
60 $chunk = $chunk->getTag("Level");
61 if(!($chunk instanceof CompoundTag)){
62 throw new CorruptedChunkException("'Level' key is missing from chunk NBT");
63 }
64
65 $legacyGeneratedTag = $chunk->getTag("TerrainGenerated");
66 if($legacyGeneratedTag instanceof ByteTag && $legacyGeneratedTag->getValue() === 0){
67 //In legacy PM before 3.0, PM used to save MCRegion chunks even when they weren't generated. In these cases
68 //(we'll see them in old worlds), some of the tags which we expect to always be present, will be missing.
69 //If TerrainGenerated (PM-specific tag from the olden days) is false, toss the chunk data and don't bother
70 //trying to read it.
71 return null;
72 }
73
74 $makeBiomeArray = function(string $biomeIds) : PalettedBlockArray{
75 if(strlen($biomeIds) !== 256){
76 throw new CorruptedChunkException("Expected biome array to be exactly 256 bytes, got " . strlen($biomeIds));
77 }
78 return ChunkUtils::extrapolate3DBiomes($biomeIds);
79 };
80 if(($biomeColorsTag = $chunk->getTag("BiomeColors")) instanceof IntArrayTag){
81 $biomes3d = $makeBiomeArray(ChunkUtils::convertBiomeColors($biomeColorsTag->getValue())); //Convert back to original format
82 }elseif(($biomesTag = $chunk->getTag("Biomes")) instanceof ByteArrayTag){
83 $biomes3d = $makeBiomeArray($biomesTag->getValue());
84 }else{
85 $biomes3d = new PalettedBlockArray(BiomeIds::OCEAN);
86 }
87
88 $subChunks = [];
89 $fullIds = self::readFixedSizeByteArray($chunk, "Blocks", 32768);
90 $fullData = self::readFixedSizeByteArray($chunk, "Data", 16384);
91
92 for($y = 0; $y < 8; ++$y){
93 $subChunks[$y] = new SubChunk(Block::EMPTY_STATE_ID, [$this->palettizeLegacySubChunkFromColumn(
94 $fullIds,
95 $fullData,
96 $y,
97 new \PrefixedLogger($logger, "Subchunk y=$y"),
98 )], clone $biomes3d);
99 }
100 for($y = Chunk::MIN_SUBCHUNK_INDEX; $y <= Chunk::MAX_SUBCHUNK_INDEX; ++$y){
101 if(!isset($subChunks[$y])){
102 $subChunks[$y] = new SubChunk(Block::EMPTY_STATE_ID, [], clone $biomes3d);
103 }
104 }
105
106 return new LoadedChunkData(
107 data: new ChunkData(
108 $subChunks,
109 $chunk->getByte("TerrainPopulated", 0) !== 0,
110 ($entitiesTag = $chunk->getTag("Entities")) instanceof ListTag ? self::getCompoundList("Entities", $entitiesTag) : [],
111 ($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [],
112 ),
113 upgraded: true,
114 fixerFlags: LoadedChunkData::FIXER_FLAG_ALL
115 );
116 }
117
118 protected static function getRegionFileExtension() : string{
119 return "mcr";
120 }
121
122 protected static function getPcWorldFormatVersion() : int{
123 return 19132;
124 }
125
126 public function getWorldMinY() : int{
127 return 0;
128 }
129
130 public function getWorldMaxY() : int{
131 //TODO: add world height options
132 return 128;
133 }
134}
static extrapolate3DBiomes(string $biomes2d)
Definition: ChunkUtils.php:51
static convertBiomeColors(array $array)
Definition: ChunkUtils.php:40
deserializeChunk(string $data, \Logger $logger)
Definition: McRegion.php:49