diff --git a/src/pocketmine/level/format/generic/EmptySubChunk.php b/src/pocketmine/level/format/generic/EmptySubChunk.php index e810b8771..a7a5e702b 100644 --- a/src/pocketmine/level/format/generic/EmptySubChunk.php +++ b/src/pocketmine/level/format/generic/EmptySubChunk.php @@ -59,14 +59,6 @@ class EmptySubChunk extends SubChunk{ return false; } - public function getBlockSkyLight(int $x, int $y, int $z) : int{ - return 15; - } - - public function setBlockSkyLight(int $x, int $y, int $z, int $level) : bool{ - return false; - } - public function getBlockLight(int $x, int $y, int $z) : int{ return 0; } @@ -75,6 +67,14 @@ class EmptySubChunk extends SubChunk{ return false; } + public function getBlockSkyLight(int $x, int $y, int $z) : int{ + return 15; + } + + public function setBlockSkyLight(int $x, int $y, int $z, int $level) : bool{ + return false; + } + public function getBlockIdColumn(int $x, int $z) : string{ return "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; } diff --git a/src/pocketmine/level/format/generic/GenericChunk.php b/src/pocketmine/level/format/generic/GenericChunk.php index 5ad0583f7..8cb089603 100644 --- a/src/pocketmine/level/format/generic/GenericChunk.php +++ b/src/pocketmine/level/format/generic/GenericChunk.php @@ -281,7 +281,7 @@ class GenericChunk implements Chunk{ for($z = 0; $z < 16; ++$z){ $heightMap = $this->getHeightMap($x, $z); - $y = min($this->getHighestSubChunkIndex() << 4, $heightMap); + $y = min(($this->getHighestSubChunkIndex() + 1) << 4, $heightMap); for(; $y > $heightMap; --$y){ $this->setBlockSkyLight($x, $y, $z, 15); @@ -652,12 +652,7 @@ class GenericChunk implements Chunk{ $subChunks = []; $count = $stream->getByte(); for($y = 0; $y < $count; ++$y){ - $subChunks[$stream->getByte()] = new SubChunk( - $stream->get(4096), //blockIds - $stream->get(2048), //blockData - $stream->get(2048), //skyLight - $stream->get(2048) //blockLight - ); + $subChunks[$stream->getByte()] = SubChunk::fastDeserialize($stream->get(10240)); } $heightMap = array_values(unpack("C*", $stream->get(256))); $biomeIds = $stream->get(256); diff --git a/src/pocketmine/level/format/generic/SubChunk.php b/src/pocketmine/level/format/generic/SubChunk.php index 72e35c0cf..d19131d60 100644 --- a/src/pocketmine/level/format/generic/SubChunk.php +++ b/src/pocketmine/level/format/generic/SubChunk.php @@ -39,11 +39,11 @@ class SubChunk{ } } - public function __construct(string $ids = "", string $data = "", string $blockLight = "", string $skyLight = ""){ + public function __construct(string $ids = "", string $data = "", string $skyLight = "", string $blockLight = ""){ self::assignData($this->ids, $ids, 4096); self::assignData($this->data, $data, 2048); - self::assignData($this->blockLight, $blockLight, 2048); self::assignData($this->skyLight, $skyLight, 2048); + self::assignData($this->blockLight, $blockLight, 2048); } public function isEmpty() : bool{ @@ -115,26 +115,6 @@ class SubChunk{ return $changed; } - public function getBlockSkyLight(int $x, int $y, int $z) : int{ - $byte = ord($this->skyLight{($x << 7) + ($z << 3) + ($y >> 1)}); - if(($y & 1) === 0){ - return $byte & 0x0f; - }else{ - return $byte >> 4; - } - } - - public function setBlockSkyLight(int $x, int $y, int $z, int $level) : bool{ - $i = ($x << 7) + ($z << 3) + ($y >> 1); - $byte = ord($this->skyLight{$i}); - if(($y & 1) === 0){ - $this->skyLight{$i} = chr(($byte & 0xf0) | ($level & 0x0f)); - }else{ - $this->skyLight{$i} = chr((($level & 0x0f) << 4) | ($byte & 0x0f)); - } - return true; - } - public function getBlockLight(int $x, int $y, int $z) : int{ $byte = ord($this->blockLight{($x << 7) + ($z << 3) + ($y >> 1)}); if(($y & 1) === 0){ @@ -155,6 +135,26 @@ class SubChunk{ return true; } + public function getBlockSkyLight(int $x, int $y, int $z) : int{ + $byte = ord($this->skyLight{($x << 7) + ($z << 3) + ($y >> 1)}); + if(($y & 1) === 0){ + return $byte & 0x0f; + }else{ + return $byte >> 4; + } + } + + public function setBlockSkyLight(int $x, int $y, int $z, int $level) : bool{ + $i = ($x << 7) + ($z << 3) + ($y >> 1); + $byte = ord($this->skyLight{$i}); + if(($y & 1) === 0){ + $this->skyLight{$i} = chr(($byte & 0xf0) | ($level & 0x0f)); + }else{ + $this->skyLight{$i} = chr((($level & 0x0f) << 4) | ($byte & 0x0f)); + } + return true; + } + public function getHighestBlockAt(int $x, int $z) : int{ for($y = 15; $y >= 0; --$y){ if($this->ids{($x << 8) | ($z << 4) | $y} !== "\x00"){ @@ -191,23 +191,35 @@ class SubChunk{ return $this->data; } - public function getBlockLightArray() : string{ - assert(strlen($this->blockLight) === 2048, "Wrong length of light array, expecting 2048 bytes, got " . strlen($this->blockLight)); - return $this->blockLight; - } - public function getSkyLightArray() : string{ assert(strlen($this->skyLight) === 2048, "Wrong length of skylight array, expecting 2048 bytes, got " . strlen($this->skyLight)); return $this->skyLight; } + public function getBlockLightArray() : string{ + assert(strlen($this->blockLight) === 2048, "Wrong length of light array, expecting 2048 bytes, got " . strlen($this->blockLight)); + return $this->blockLight; + } + public function networkSerialize() : string{ // storage version, ids, data, skylight, blocklight return "\x00" . $this->ids . $this->data . $this->skyLight . $this->blockLight; } public function fastSerialize() : string{ - // ids, data, skylight, blocklight - return $this->ids . $this->data . $this->skyLight . $this->blockLight; + return + $this->ids . + $this->data . + $this->skyLight . + $this->blockLight; + } + + public static function fastDeserialize(string $data) : SubChunk{ + return new SubChunk( + substr($data, 0, 4096), //ids + substr($data, 4096, 2048), //data + substr($data, 6144, 2048), //sky light + substr($data, 8192, 2048) //block light + ); } } \ No newline at end of file diff --git a/src/pocketmine/level/format/region/Anvil.php b/src/pocketmine/level/format/region/Anvil.php index 250bb31d1..b385a8ddb 100644 --- a/src/pocketmine/level/format/region/Anvil.php +++ b/src/pocketmine/level/format/region/Anvil.php @@ -61,8 +61,8 @@ class Anvil extends McRegion{ "Y" => new ByteTag("Y", $y), "Blocks" => new ByteArrayTag("Blocks", GenericChunk::reorderByteArray($subChunk->getBlockIdArray())), //Generic in-memory chunks are currrently always XZY "Data" => new ByteArrayTag("Data", GenericChunk::reorderNibbleArray($subChunk->getBlockDataArray())), - "BlockLight" => new ByteArrayTag("BlockLight", GenericChunk::reorderNibbleArray($subChunk->getBlockLightArray())), - "SkyLight" => new ByteArrayTag("SkyLight", GenericChunk::reorderNibbleArray($subChunk->getSkyLightArray())) + "SkyLight" => new ByteArrayTag("SkyLight", GenericChunk::reorderNibbleArray($subChunk->getSkyLightArray())), + "BlockLight" => new ByteArrayTag("BlockLight", GenericChunk::reorderNibbleArray($subChunk->getBlockLightArray())) ]); } @@ -119,8 +119,8 @@ class Anvil extends McRegion{ $subChunks[$subChunk->Y->getValue()] = new SubChunk( GenericChunk::reorderByteArray($subChunk->Blocks->getValue()), GenericChunk::reorderNibbleArray($subChunk->Data->getValue()), - GenericChunk::reorderNibbleArray($subChunk->BlockLight->getValue()), - GenericChunk::reorderNibbleArray($subChunk->SkyLight->getValue()) + GenericChunk::reorderNibbleArray($subChunk->SkyLight->getValue()), + GenericChunk::reorderNibbleArray($subChunk->BlockLight->getValue()) ); } } diff --git a/src/pocketmine/level/format/region/McRegion.php b/src/pocketmine/level/format/region/McRegion.php index 22d14b097..851582fb2 100644 --- a/src/pocketmine/level/format/region/McRegion.php +++ b/src/pocketmine/level/format/region/McRegion.php @@ -64,8 +64,8 @@ class McRegion extends BaseLevelProvider{ $ids = ""; $data = ""; - $blockLight = ""; $skyLight = ""; + $blockLight = ""; $subChunks = $chunk->getSubChunks(); for($x = 0; $x < 16; ++$x){ for($z = 0; $z < 16; ++$z){ @@ -73,8 +73,8 @@ class McRegion extends BaseLevelProvider{ $subChunk = $subChunks[$y]; $ids .= $subChunk->getBlockIdColumn($x, $z); $data .= $subChunk->getBlockDataColumn($x, $z); - $blockLight .= $subChunk->getBlockLightColumn($x, $z); $skyLight .= $subChunk->getSkyLightColumn($x, $z); + $blockLight .= $subChunk->getBlockLightColumn($x, $z); } } } @@ -138,8 +138,8 @@ class McRegion extends BaseLevelProvider{ $subChunks = []; $fullIds = isset($chunk->Blocks) ? $chunk->Blocks->getValue() : str_repeat("\x00", 32768); $fullData = isset($chunk->Data) ? $chunk->Data->getValue() : ($half = str_repeat("\x00", 16384)); - $fullBlockLight = isset($chunk->BlockLight) ? $chunk->BlockLight->getValue() : $half; $fullSkyLight = isset($chunk->SkyLight) ? $chunk->SkyLight->getValue() : str_repeat("\xff", 16384); + $fullBlockLight = isset($chunk->BlockLight) ? $chunk->BlockLight->getValue() : $half; for($y = 0; $y < 8; ++$y){ $offset = ($y << 4); @@ -154,19 +154,19 @@ class McRegion extends BaseLevelProvider{ $data .= substr($fullData, $offset, 8); $offset += 64; } - $blockLight = ""; - $offset = ($y << 3); - for($i = 0; $i < 256; ++$i){ - $blockLight .= substr($fullBlockLight, $offset, 8); - $offset += 64; - } $skyLight = ""; $offset = ($y << 3); for($i = 0; $i < 256; ++$i){ $skyLight .= substr($fullSkyLight, $offset, 8); $offset += 64; } - $subChunks[$y] = new SubChunk($ids, $data, $blockLight, $skyLight); + $blockLight = ""; + $offset = ($y << 3); + for($i = 0; $i < 256; ++$i){ + $blockLight .= substr($fullBlockLight, $offset, 8); + $offset += 64; + } + $subChunks[$y] = new SubChunk($ids, $data, $skyLight, $blockLight); } if(isset($chunk->BiomeColors)){ diff --git a/src/pocketmine/level/format/region/PMAnvil.php b/src/pocketmine/level/format/region/PMAnvil.php index d1e9f0174..99ae99ff8 100644 --- a/src/pocketmine/level/format/region/PMAnvil.php +++ b/src/pocketmine/level/format/region/PMAnvil.php @@ -65,8 +65,8 @@ class PMAnvil extends Anvil{ "Y" => new ByteTag("Y", $y), "Blocks" => new ByteArrayTag("Blocks", $subChunk->getBlockIdArray()), "Data" => new ByteArrayTag("Data", $subChunk->getBlockDataArray()), - "BlockLight" => new ByteArrayTag("BlockLight", $subChunk->getBlockLightArray()), - "SkyLight" => new ByteArrayTag("SkyLight", $subChunk->getSkyLightArray()) + "SkyLight" => new ByteArrayTag("SkyLight", $subChunk->getSkyLightArray()), + "BlockLight" => new ByteArrayTag("BlockLight", $subChunk->getBlockLightArray()) ]); } @@ -123,8 +123,8 @@ class PMAnvil extends Anvil{ $subChunks[$subChunk->Y->getValue()] = new SubChunk( $subChunk->Blocks->getValue(), $subChunk->Data->getValue(), - $subChunk->BlockLight->getValue(), - $subChunk->SkyLight->getValue() + $subChunk->SkyLight->getValue(), + $subChunk->BlockLight->getValue() ); } }