diff --git a/src/world/format/SubChunk.php b/src/world/format/SubChunk.php index e4653ccdb..510d34487 100644 --- a/src/world/format/SubChunk.php +++ b/src/world/format/SubChunk.php @@ -31,17 +31,31 @@ class SubChunk{ public const COORD_MASK = ~(~0 << self::COORD_BIT_SIZE); public const EDGE_LENGTH = 1 << self::COORD_BIT_SIZE; + private int $emptyBlockId; + private PalettedBlockArray $blockLayer; + private PalettedBlockArray $liquidLayer; + private PalettedBlockArray $biomes; + private ?LightArray $skyLight; + private ?LightArray $blockLight; + /** * SubChunk constructor. */ public function __construct( - private int $emptyBlockId, - private ?PalettedBlockArray $blockLayer, - private ?PalettedBlockArray $liquidLayer, - private PalettedBlockArray $biomes, - private ?LightArray $skyLight = null, - private ?LightArray $blockLight = null - ){} + int $emptyBlockId, + ?PalettedBlockArray $blockLayer, + ?PalettedBlockArray $liquidLayer, + PalettedBlockArray $biomes, + ?LightArray $skyLight = null, + ?LightArray $blockLight = null + ){ + $this->emptyBlockId = $emptyBlockId; + $this->blockLayer = $blockLayer ?? new PalettedBlockArray($emptyBlockId); + $this->liquidLayer = $liquidLayer ?? new PalettedBlockArray($emptyBlockId); + $this->biomes = $biomes; + $this->skyLight = $skyLight; + $this->blockLight = $blockLight; + } /** * Returns whether this subchunk contains any non-air blocks. @@ -58,7 +72,8 @@ class SubChunk{ * This may report non-empty erroneously if the chunk has been modified and not garbage-collected. */ public function isEmptyFast() : bool{ - return $this->blockLayer === null && $this->liquidLayer === null; + return $this->blockLayer->getBitsPerBlock() === 0 && $this->blockLayer->get(0, 0, 0) === $this->emptyBlockId && + $this->liquidLayer->getBitsPerBlock() === 0 && $this->liquidLayer->get(0, 0, 0) === $this->emptyBlockId; } /** @@ -68,16 +83,10 @@ class SubChunk{ public function getEmptyBlockId() : int{ return $this->emptyBlockId; } public function getBlockStateId(int $x, int $y, int $z) : int{ - if($this->blockLayer === null){ - return $this->emptyBlockId; - } return $this->blockLayer->get($x, $y, $z); } public function setBlockStateId(int $x, int $y, int $z, int $block) : void{ - if($this->blockLayer === null){ - $this->blockLayer = new PalettedBlockArray($this->emptyBlockId); - } $this->blockLayer->set($x, $y, $z, $block); } @@ -87,36 +96,26 @@ class SubChunk{ * @phpstan-return list */ public function getBlockLayers() : array{ - $layers = []; - if($this->blockLayer !== null){ - $layers[] = $this->blockLayer; - } - if($this->liquidLayer !== null){ - $layers[] = $this->liquidLayer; - } - return $layers; + return [$this->blockLayer, $this->liquidLayer]; } - public function getBlockLayer() : ?PalettedBlockArray{ + public function getBlockLayer() : PalettedBlockArray{ return $this->blockLayer; } - public function setBlockLayer(?PalettedBlockArray $blockLayer) : void{ + public function setBlockLayer(PalettedBlockArray $blockLayer) : void{ $this->blockLayer = $blockLayer; } - public function getLiquidLayer() : ?PalettedBlockArray{ + public function getLiquidLayer() : PalettedBlockArray{ return $this->liquidLayer; } - public function setLiquidLayer(?PalettedBlockArray $liquidLayer) : void{ + public function setLiquidLayer(PalettedBlockArray $liquidLayer) : void{ $this->liquidLayer = $liquidLayer; } public function getHighestBlockAt(int $x, int $z) : ?int{ - if($this->blockLayer === null){ - return null; - } for($y = self::EDGE_LENGTH - 1; $y >= 0; --$y){ if($this->blockLayer->get($x, $y, $z) !== $this->emptyBlockId){ return $y; @@ -152,18 +151,8 @@ class SubChunk{ } public function collectGarbage() : void{ - if($this->blockLayer !== null){ - $this->blockLayer->collectGarbage(); - if($this->blockLayer->getBitsPerBlock() === 0 && $this->blockLayer->get(0, 0, 0) === $this->emptyBlockId){ - $this->blockLayer = null; - } - } - if($this->liquidLayer !== null){ - $this->liquidLayer->collectGarbage(); - if($this->liquidLayer->getBitsPerBlock() === 0 && $this->liquidLayer->get(0, 0, 0) === $this->emptyBlockId){ - $this->liquidLayer = null; - } - } + $this->blockLayer->collectGarbage(); + $this->liquidLayer->collectGarbage(); $this->biomes->collectGarbage(); if($this->skyLight !== null && $this->skyLight->isUniform(0)){ @@ -175,12 +164,8 @@ class SubChunk{ } public function __clone(){ - if($this->blockLayer !== null){ - $this->blockLayer = clone $this->blockLayer; - } - if($this->liquidLayer !== null){ - $this->liquidLayer = clone $this->liquidLayer; - } + $this->blockLayer = clone $this->blockLayer; + $this->liquidLayer = clone $this->liquidLayer; $this->biomes = clone $this->biomes; if($this->skyLight !== null){ diff --git a/src/world/format/io/FastChunkSerializer.php b/src/world/format/io/FastChunkSerializer.php index 10a316d36..30bd5fe65 100644 --- a/src/world/format/io/FastChunkSerializer.php +++ b/src/world/format/io/FastChunkSerializer.php @@ -75,22 +75,10 @@ final class FastChunkSerializer{ $stream->putByte($y); $stream->putInt($subChunk->getEmptyBlockId()); - // Write block layer presence and data - $blockLayer = $subChunk->getBlockLayer(); - $stream->putByte($blockLayer !== null ? 1 : 0); - if($blockLayer !== null){ - self::serializePalettedArray($stream, $blockLayer); - } - - // Write liquid layer presence and data - $liquidLayer = $subChunk->getLiquidLayer(); - $stream->putByte($liquidLayer !== null ? 1 : 0); - if($liquidLayer !== null){ - self::serializePalettedArray($stream, $liquidLayer); - } - + // Write block and liquid layers (always present) + self::serializePalettedArray($stream, $subChunk->getBlockLayer()); + self::serializePalettedArray($stream, $subChunk->getLiquidLayer()); self::serializePalettedArray($stream, $subChunk->getBiomeArray()); - } return $stream->getBuffer(); @@ -122,19 +110,11 @@ final class FastChunkSerializer{ $y = Binary::signByte($stream->getByte()); $airBlockId = $stream->getInt(); - // Read block layer - $blockLayer = null; - if($stream->getByte() !== 0){ - $blockLayer = self::deserializePalettedArray($stream); - } - - // Read liquid layer - $liquidLayer = null; - if($stream->getByte() !== 0){ - $liquidLayer = self::deserializePalettedArray($stream); - } - + // Read block and liquid layers (always present) + $blockLayer = self::deserializePalettedArray($stream); + $liquidLayer = self::deserializePalettedArray($stream); $biomeArray = self::deserializePalettedArray($stream); + $subChunks[$y] = new SubChunk($airBlockId, $blockLayer, $liquidLayer, $biomeArray); }