mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-08-19 17:40:38 +00:00
Refactor SubChunk to use non-nullable block and liquid layers
- Changed SubChunk constructor to accept null for layers and initialize empty PalettedBlockArray internally - Updated all SubChunk getters to return non-nullable PalettedBlockArray - Modified serialization/deserialization logic to check for layer emptiness instead of null - Updated all SubChunk constructor calls across codebase to pass null for empty layers - Simplified code by removing unnecessary null checks throughout the codebase - Updated tests to match new SubChunk API
This commit is contained in:
parent
8005c74681
commit
ba2a7cceaf
@ -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<PalettedBlockArray>
|
||||
*/
|
||||
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){
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user