From 01f8116cdd025e524e287c36a6af9299739da62e Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 7 Sep 2020 14:43:26 +0100 Subject: [PATCH] Fix some of the implicit immutability issues of EmptySubChunk it's useful to have an immutable stub around for the sake of feeding back dummy read values, but for write values it has to barf instead of being quiet. There's still some issues with LightArray which I don't currently have a solution for, but I'm thinking about separating light storage from chunks anyway. --- src/world/format/Chunk.php | 21 ++++++++++++++------- src/world/format/EmptySubChunk.php | 12 ------------ src/world/format/SubChunkInterface.php | 6 ------ src/world/generator/Flat.php | 2 +- src/world/light/LightPopulationTask.php | 4 ++-- tests/phpstan/configs/l8-baseline.neon | 5 +++++ 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/world/format/Chunk.php b/src/world/format/Chunk.php index cf11ad540..e842fef96 100644 --- a/src/world/format/Chunk.php +++ b/src/world/format/Chunk.php @@ -152,7 +152,7 @@ class Chunk{ * Sets the blockstate at the given coordinate by internal ID. */ public function setFullBlock(int $x, int $y, int $z, int $block) : void{ - $this->getSubChunk($y >> 4)->setFullBlock($x, $y & 0xf, $z, $block); + $this->getWritableSubChunk($y >> 4)->setFullBlock($x, $y & 0xf, $z, $block); $this->dirtyFlags |= self::DIRTY_FLAG_TERRAIN; } @@ -178,12 +178,12 @@ class Chunk{ * @param int $level 0-15 */ public function setBlockSkyLight(int $x, int $y, int $z, int $level) : void{ - $this->getSubChunk($y >> 4)->getBlockSkyLightArray()->set($x & 0xf, $y & 0x0f, $z & 0xf, $level); + $this->getWritableSubChunk($y >> 4)->getBlockSkyLightArray()->set($x & 0xf, $y & 0x0f, $z & 0xf, $level); } public function setAllBlockSkyLight(int $level) : void{ for($y = $this->subChunks->count() - 1; $y >= 0; --$y){ - $this->getSubChunk($y)->setBlockSkyLightArray(LightArray::fill($level)); + $this->getWritableSubChunk($y)->setBlockSkyLightArray(LightArray::fill($level)); } } @@ -209,12 +209,12 @@ class Chunk{ * @param int $level 0-15 */ public function setBlockLight(int $x, int $y, int $z, int $level) : void{ - $this->getSubChunk($y >> 4)->getBlockLightArray()->set($x & 0xf, $y & 0x0f, $z & 0xf, $level); + $this->getWritableSubChunk($y >> 4)->getBlockLightArray()->set($x & 0xf, $y & 0x0f, $z & 0xf, $level); } public function setAllBlockLight(int $level) : void{ for($y = $this->subChunks->count() - 1; $y >= 0; --$y){ - $this->getSubChunk($y)->setBlockLightArray(LightArray::fill($level)); + $this->getWritableSubChunk($y)->setBlockLightArray(LightArray::fill($level)); } } @@ -340,10 +340,10 @@ class Chunk{ $highestHeightMap = max($this->heightMap->getValues()); $lowestFullyLitSubChunk = ($highestHeightMap >> 4) + (($highestHeightMap & 0xf) !== 0 ? 1 : 0); for($y = 0; $y < $lowestFullyLitSubChunk; $y++){ - $this->getSubChunk($y)->setBlockSkyLightArray(LightArray::fill(0)); + $this->getWritableSubChunk($y)->setBlockSkyLightArray(LightArray::fill(0)); } for($y = $lowestFullyLitSubChunk, $yMax = $this->subChunks->count(); $y < $yMax; $y++){ - $this->getSubChunk($y)->setBlockSkyLightArray(LightArray::fill(15)); + $this->getWritableSubChunk($y)->setBlockSkyLightArray(LightArray::fill(15)); } for($x = 0; $x < 16; ++$x){ @@ -623,6 +623,13 @@ class Chunk{ return $this->subChunks[$y]; } + public function getWritableSubChunk(int $y) : SubChunk{ + if($y < 0 || $y >= $this->subChunks->getSize()){ + throw new \InvalidArgumentException("Cannot get subchunk $y for writing"); + } + return $this->subChunks[$y]; + } + /** * Sets a subchunk in the chunk index */ diff --git a/src/world/format/EmptySubChunk.php b/src/world/format/EmptySubChunk.php index d4beb1931..b28450b0a 100644 --- a/src/world/format/EmptySubChunk.php +++ b/src/world/format/EmptySubChunk.php @@ -47,10 +47,6 @@ class EmptySubChunk implements SubChunkInterface{ return 0; } - public function setFullBlock(int $x, int $y, int $z, int $block) : void{ - - } - public function getBlockLayers() : array{ return []; } @@ -63,15 +59,7 @@ class EmptySubChunk implements SubChunkInterface{ return new LightArray(LightArray::ZERO); } - public function setBlockLightArray(LightArray $data) : void{ - - } - public function getBlockSkyLightArray() : LightArray{ return new LightArray(LightArray::FIFTEEN); } - - public function setBlockSkyLightArray(LightArray $data) : void{ - - } } diff --git a/src/world/format/SubChunkInterface.php b/src/world/format/SubChunkInterface.php index d2daa72fe..25f4cce28 100644 --- a/src/world/format/SubChunkInterface.php +++ b/src/world/format/SubChunkInterface.php @@ -40,8 +40,6 @@ interface SubChunkInterface{ public function getFullBlock(int $x, int $y, int $z) : int; - public function setFullBlock(int $x, int $y, int $z, int $block) : void; - /** * @return PalettedBlockArray[] */ @@ -51,9 +49,5 @@ interface SubChunkInterface{ public function getBlockSkyLightArray() : LightArray; - public function setBlockSkyLightArray(LightArray $data) : void; - public function getBlockLightArray() : LightArray; - - public function setBlockLightArray(LightArray $data) : void; } diff --git a/src/world/generator/Flat.php b/src/world/generator/Flat.php index 5715ffb66..87b8b3fe2 100644 --- a/src/world/generator/Flat.php +++ b/src/world/generator/Flat.php @@ -156,7 +156,7 @@ class Flat extends Generator{ $count = count($this->structure); for($sy = 0; $sy < $count; $sy += 16){ - $subchunk = $this->chunk->getSubChunk($sy >> 4); + $subchunk = $this->chunk->getWritableSubChunk($sy >> 4); for($y = 0; $y < 16 and isset($this->structure[$y | $sy]); ++$y){ $id = $this->structure[$y | $sy]; diff --git a/src/world/light/LightPopulationTask.php b/src/world/light/LightPopulationTask.php index 8fa5776e9..b4b33ff86 100644 --- a/src/world/light/LightPopulationTask.php +++ b/src/world/light/LightPopulationTask.php @@ -94,10 +94,10 @@ class LightPopulationTask extends AsyncTask{ $blockLightArrays = igbinary_unserialize($this->resultBlockLightArrays); foreach($skyLightArrays as $y => $array){ - $chunk->getSubChunk($y)->setBlockSkyLightArray($array); + $chunk->getWritableSubChunk($y)->setBlockSkyLightArray($array); } foreach($blockLightArrays as $y => $array){ - $chunk->getSubChunk($y)->setBlockLightArray($array); + $chunk->getWritableSubChunk($y)->setBlockLightArray($array); } $chunk->setLightPopulated(); } diff --git a/tests/phpstan/configs/l8-baseline.neon b/tests/phpstan/configs/l8-baseline.neon index 506fef3bf..d6678176e 100644 --- a/tests/phpstan/configs/l8-baseline.neon +++ b/tests/phpstan/configs/l8-baseline.neon @@ -760,6 +760,11 @@ parameters: count: 1 path: ../../../src/world/format/Chunk.php + - + message: "#^Method pocketmine\\\\world\\\\format\\\\Chunk\\:\\:getWritableSubChunk\\(\\) should return pocketmine\\\\world\\\\format\\\\SubChunk but returns pocketmine\\\\world\\\\format\\\\SubChunk\\|null\\.$#" + count: 1 + path: ../../../src/world/format/Chunk.php + - message: "#^Method pocketmine\\\\world\\\\format\\\\HeightArray\\:\\:get\\(\\) should return int but returns int\\|null\\.$#" count: 1