mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 00:07:30 +00:00
BlockFactory: change property cache arrays to use regular arrays instead of SplFixedArray
this does come at a performance cost, but is necessary for metadata expansion. we finally concede that this is not going to happen without BC breaks, however small they might be ...
This commit is contained in:
parent
b52bb5016c
commit
334c9daa6a
@ -58,8 +58,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemIds;
|
||||
use pocketmine\item\ToolTier;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function array_fill;
|
||||
use function array_filter;
|
||||
use pocketmine\world\light\LightUpdate;
|
||||
use function get_class;
|
||||
use function min;
|
||||
|
||||
@ -89,32 +88,27 @@ class BlockFactory{
|
||||
private array $mappedStateIndexes = [];
|
||||
|
||||
/**
|
||||
* @var \SplFixedArray|int[]
|
||||
* @phpstan-var \SplFixedArray<int>
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
public $light;
|
||||
public array $light = [];
|
||||
/**
|
||||
* @var \SplFixedArray|int[]
|
||||
* @phpstan-var \SplFixedArray<int>
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
public $lightFilter;
|
||||
public array $lightFilter = [];
|
||||
/**
|
||||
* @var \SplFixedArray|bool[]
|
||||
* @phpstan-var \SplFixedArray<bool>
|
||||
* @var true[]
|
||||
* @phpstan-var array<int, true>
|
||||
*/
|
||||
public $blocksDirectSkyLight;
|
||||
public array $blocksDirectSkyLight = [];
|
||||
/**
|
||||
* @var \SplFixedArray|float[]
|
||||
* @phpstan-var \SplFixedArray<float>
|
||||
* @var float[]
|
||||
* @phpstan-var array<int, float>
|
||||
*/
|
||||
public $blastResistance;
|
||||
public array $blastResistance = [];
|
||||
|
||||
public function __construct(){
|
||||
$this->light = \SplFixedArray::fromArray(array_fill(0, 1024 << Block::INTERNAL_METADATA_BITS, 0));
|
||||
$this->lightFilter = \SplFixedArray::fromArray(array_fill(0, 1024 << Block::INTERNAL_METADATA_BITS, 1));
|
||||
$this->blocksDirectSkyLight = \SplFixedArray::fromArray(array_fill(0, 1024 << Block::INTERNAL_METADATA_BITS, false));
|
||||
$this->blastResistance = \SplFixedArray::fromArray(array_fill(0, 1024 << Block::INTERNAL_METADATA_BITS, 0.0));
|
||||
|
||||
$railBreakInfo = new BlockBreakInfo(0.7);
|
||||
$this->registerAllMeta(new ActivatorRail(new BID(Ids::ACTIVATOR_RAIL, 0), "Activator Rail", $railBreakInfo));
|
||||
$this->registerAllMeta(new Air(new BID(Ids::AIR, 0), "Air", BlockBreakInfo::indestructible(-1.0)));
|
||||
@ -1031,11 +1025,13 @@ class BlockFactory{
|
||||
$this->mappedStateIndexes[$index] = $fullId;
|
||||
}else{
|
||||
$this->fullList[$index] = $block;
|
||||
$this->blastResistance[$index] = $block->getBreakInfo()->getBlastResistance();
|
||||
$this->light[$index] = $block->getLightLevel();
|
||||
$this->lightFilter[$index] = min(15, $block->getLightFilter() + LightUpdate::BASE_LIGHT_FILTER);
|
||||
if($block->blocksDirectSkyLight()){
|
||||
$this->blocksDirectSkyLight[$index] = true;
|
||||
}
|
||||
}
|
||||
$this->light[$index] = $block->getLightLevel();
|
||||
$this->lightFilter[$index] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter
|
||||
$this->blocksDirectSkyLight[$index] = $block->blocksDirectSkyLight();
|
||||
$this->blastResistance[$index] = $block->getBreakInfo()->getBlastResistance();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,7 +129,7 @@ class Explosion{
|
||||
|
||||
$state = $this->subChunkExplorer->currentSubChunk->getFullBlock($vBlockX & SubChunk::COORD_MASK, $vBlockY & SubChunk::COORD_MASK, $vBlockZ & SubChunk::COORD_MASK);
|
||||
|
||||
$blastResistance = $blockFactory->blastResistance[$state];
|
||||
$blastResistance = $blockFactory->blastResistance[$state] ?? 0;
|
||||
if($blastResistance >= 0){
|
||||
$blastForce -= ($blastResistance / 5 + 0.3) * $this->stepLen;
|
||||
if($blastForce > 0){
|
||||
|
@ -32,18 +32,18 @@ use function max;
|
||||
class BlockLightUpdate extends LightUpdate{
|
||||
|
||||
/**
|
||||
* @var \SplFixedArray|int[]
|
||||
* @phpstan-var \SplFixedArray<int>
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private $lightEmitters;
|
||||
|
||||
/**
|
||||
* @param \SplFixedArray|int[] $lightFilters
|
||||
* @param \SplFixedArray|int[] $lightEmitters
|
||||
* @phpstan-param \SplFixedArray<int> $lightFilters
|
||||
* @phpstan-param \SplFixedArray<int> $lightEmitters
|
||||
* @param int[] $lightFilters
|
||||
* @param int[] $lightEmitters
|
||||
* @phpstan-param array<int, int> $lightFilters
|
||||
* @phpstan-param array<int, int> $lightEmitters
|
||||
*/
|
||||
public function __construct(SubChunkExplorer $subChunkExplorer, \SplFixedArray $lightFilters, \SplFixedArray $lightEmitters){
|
||||
public function __construct(SubChunkExplorer $subChunkExplorer, array $lightFilters, array $lightEmitters){
|
||||
parent::__construct($subChunkExplorer, $lightFilters);
|
||||
$this->lightEmitters = $lightEmitters;
|
||||
}
|
||||
@ -55,7 +55,7 @@ class BlockLightUpdate extends LightUpdate{
|
||||
public function recalculateNode(int $x, int $y, int $z) : void{
|
||||
if($this->subChunkExplorer->moveTo($x, $y, $z) !== SubChunkExplorerStatus::INVALID){
|
||||
$block = $this->subChunkExplorer->currentSubChunk->getFullBlock($x & SubChunk::COORD_MASK, $y & SubChunk::COORD_MASK, $z & SubChunk::COORD_MASK);
|
||||
$this->setAndUpdateLight($x, $y, $z, max($this->lightEmitters[$block], $this->getHighestAdjacentLight($x, $y, $z) - $this->lightFilters[$block]));
|
||||
$this->setAndUpdateLight($x, $y, $z, max($this->lightEmitters[$block] ?? 0, $this->getHighestAdjacentLight($x, $y, $z) - ($this->lightFilters[$block] ?? self::BASE_LIGHT_FILTER)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class BlockLightUpdate extends LightUpdate{
|
||||
|
||||
foreach($subChunk->getBlockLayers() as $layer){
|
||||
foreach($layer->getPalette() as $state){
|
||||
if($this->lightEmitters[$state] > 0){
|
||||
if(($this->lightEmitters[$state] ?? 0) > 0){
|
||||
$lightSources += $this->scanForLightEmittingBlocks($subChunk, $chunkX << SubChunk::COORD_BIT_SIZE, $subChunkY << SubChunk::COORD_BIT_SIZE, $chunkZ << SubChunk::COORD_BIT_SIZE);
|
||||
break 2;
|
||||
}
|
||||
@ -87,7 +87,7 @@ class BlockLightUpdate extends LightUpdate{
|
||||
for($x = 0; $x < SubChunk::EDGE_LENGTH; ++$x){
|
||||
for($z = 0; $z < SubChunk::EDGE_LENGTH; ++$z){
|
||||
for($y = 0; $y < SubChunk::EDGE_LENGTH; ++$y){
|
||||
$light = $this->lightEmitters[$subChunk->getFullBlock($x, $y, $z)];
|
||||
$light = $this->lightEmitters[$subChunk->getFullBlock($x, $y, $z)] ?? 0;
|
||||
if($light > 0){
|
||||
$this->setAndUpdateLight(
|
||||
$baseX + $x,
|
||||
|
@ -41,9 +41,11 @@ abstract class LightUpdate{
|
||||
[ 0, 0, -1]
|
||||
];
|
||||
|
||||
public const BASE_LIGHT_FILTER = 1;
|
||||
|
||||
/**
|
||||
* @var \SplFixedArray|int[]
|
||||
* @phpstan-var \SplFixedArray<int>
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
protected $lightFilters;
|
||||
|
||||
@ -57,10 +59,10 @@ abstract class LightUpdate{
|
||||
protected $subChunkExplorer;
|
||||
|
||||
/**
|
||||
* @param \SplFixedArray|int[] $lightFilters
|
||||
* @phpstan-param \SplFixedArray<int> $lightFilters
|
||||
* @param int[] $lightFilters
|
||||
* @phpstan-param array<int, int> $lightFilters
|
||||
*/
|
||||
public function __construct(SubChunkExplorer $subChunkExplorer, \SplFixedArray $lightFilters){
|
||||
public function __construct(SubChunkExplorer $subChunkExplorer, array $lightFilters){
|
||||
$this->lightFilters = $lightFilters;
|
||||
|
||||
$this->subChunkExplorer = $subChunkExplorer;
|
||||
@ -196,7 +198,7 @@ abstract class LightUpdate{
|
||||
$ly = $y & SubChunk::COORD_MASK;
|
||||
$lz = $z & SubChunk::COORD_MASK;
|
||||
$current = $lightArray->get($lx, $ly, $lz);
|
||||
$potentialLight = $newAdjacentLevel - $this->lightFilters[$this->subChunkExplorer->currentSubChunk->getFullBlock($lx, $ly, $lz)];
|
||||
$potentialLight = $newAdjacentLevel - ($this->lightFilters[$this->subChunkExplorer->currentSubChunk->getFullBlock($lx, $ly, $lz)] ?? self::BASE_LIGHT_FILTER);
|
||||
|
||||
if($current < $potentialLight){
|
||||
$lightArray->set($lx, $ly, $lz, $potentialLight);
|
||||
|
@ -35,18 +35,18 @@ use function max;
|
||||
class SkyLightUpdate extends LightUpdate{
|
||||
|
||||
/**
|
||||
* @var \SplFixedArray|bool[]
|
||||
* @phpstan-var \SplFixedArray<bool>
|
||||
* @var true[]
|
||||
* @phpstan-var array<int, true>
|
||||
*/
|
||||
private $directSkyLightBlockers;
|
||||
|
||||
/**
|
||||
* @param \SplFixedArray|int[] $lightFilters
|
||||
* @param \SplFixedArray|bool[] $directSkyLightBlockers
|
||||
* @phpstan-param \SplFixedArray<int> $lightFilters
|
||||
* @phpstan-param \SplFixedArray<bool> $directSkyLightBlockers
|
||||
* @param int[] $lightFilters
|
||||
* @param true[] $directSkyLightBlockers
|
||||
* @phpstan-param array<int, int> $lightFilters
|
||||
* @phpstan-param array<int, true> $directSkyLightBlockers
|
||||
*/
|
||||
public function __construct(SubChunkExplorer $subChunkExplorer, \SplFixedArray $lightFilters, \SplFixedArray $directSkyLightBlockers){
|
||||
public function __construct(SubChunkExplorer $subChunkExplorer, array $lightFilters, array $directSkyLightBlockers){
|
||||
parent::__construct($subChunkExplorer, $lightFilters);
|
||||
$this->directSkyLightBlockers = $directSkyLightBlockers;
|
||||
}
|
||||
@ -78,7 +78,7 @@ class SkyLightUpdate extends LightUpdate{
|
||||
$newHeightMap = self::recalculateHeightMapColumn($chunk, $x & Chunk::COORD_MASK, $z & Chunk::COORD_MASK, $this->directSkyLightBlockers);
|
||||
$chunk->setHeightMap($x & Chunk::COORD_MASK, $z & Chunk::COORD_MASK, $newHeightMap);
|
||||
}elseif($yPlusOne > $oldHeightMap){ //Block changed above the heightmap.
|
||||
if($this->directSkyLightBlockers[$source]){
|
||||
if(isset($this->directSkyLightBlockers[$source])){
|
||||
$chunk->setHeightMap($x & Chunk::COORD_MASK, $z & Chunk::COORD_MASK, $yPlusOne);
|
||||
$newHeightMap = $yPlusOne;
|
||||
}else{ //Block changed which has no effect on direct sky light, for example placing or removing glass.
|
||||
@ -97,7 +97,7 @@ class SkyLightUpdate extends LightUpdate{
|
||||
$this->setAndUpdateLight($x, $i, $z, 15);
|
||||
}
|
||||
}else{ //No heightmap change, block changed "underground"
|
||||
$this->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentLight($x, $y, $z) - $this->lightFilters[$source]));
|
||||
$this->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentLight($x, $y, $z) - ($this->lightFilters[$source] ?? self::BASE_LIGHT_FILTER)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,10 +168,10 @@ class SkyLightUpdate extends LightUpdate{
|
||||
/**
|
||||
* Recalculates the heightmap for the whole chunk.
|
||||
*
|
||||
* @param \SplFixedArray|bool[] $directSkyLightBlockers
|
||||
* @phpstan-param \SplFixedArray<bool> $directSkyLightBlockers
|
||||
* @param true[] $directSkyLightBlockers
|
||||
* @phpstan-param array<int, true> $directSkyLightBlockers
|
||||
*/
|
||||
private static function recalculateHeightMap(Chunk $chunk, \SplFixedArray $directSkyLightBlockers) : HeightArray{
|
||||
private static function recalculateHeightMap(Chunk $chunk, array $directSkyLightBlockers) : HeightArray{
|
||||
$maxSubChunkY = Chunk::MAX_SUBCHUNK_INDEX;
|
||||
for(; $maxSubChunkY >= Chunk::MIN_SUBCHUNK_INDEX; $maxSubChunkY--){
|
||||
if(!$chunk->getSubChunk($maxSubChunkY)->isEmptyFast()){
|
||||
@ -198,7 +198,7 @@ class SkyLightUpdate extends LightUpdate{
|
||||
$result->set($x, $z, World::Y_MIN);
|
||||
}else{
|
||||
for(; $y >= World::Y_MIN; --$y){
|
||||
if($directSkyLightBlockers[$chunk->getFullBlock($x, $y, $z)]){
|
||||
if(isset($directSkyLightBlockers[$chunk->getFullBlock($x, $y, $z)])){
|
||||
$result->set($x, $z, $y + 1);
|
||||
break;
|
||||
}
|
||||
@ -214,18 +214,18 @@ class SkyLightUpdate extends LightUpdate{
|
||||
*
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
* @param \SplFixedArray|bool[] $directSkyLightBlockers
|
||||
* @phpstan-param \SplFixedArray<bool> $directSkyLightBlockers
|
||||
* @param true[] $directSkyLightBlockers
|
||||
* @phpstan-param array<int, true> $directSkyLightBlockers
|
||||
*
|
||||
* @return int New calculated heightmap value (0-256 inclusive)
|
||||
*/
|
||||
private static function recalculateHeightMapColumn(Chunk $chunk, int $x, int $z, \SplFixedArray $directSkyLightBlockers) : int{
|
||||
private static function recalculateHeightMapColumn(Chunk $chunk, int $x, int $z, array $directSkyLightBlockers) : int{
|
||||
$y = $chunk->getHighestBlockAt($x, $z);
|
||||
if($y === null){
|
||||
return World::Y_MIN;
|
||||
}
|
||||
for(; $y >= World::Y_MIN; --$y){
|
||||
if($directSkyLightBlockers[$chunk->getFullBlock($x, $y, $z)]){
|
||||
if(isset($directSkyLightBlockers[$chunk->getFullBlock($x, $y, $z)])){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +137,6 @@ class BlockTest extends TestCase{
|
||||
*/
|
||||
public function testLightFiltersValid() : void{
|
||||
foreach($this->blockFactory->lightFilter as $id => $value){
|
||||
self::assertNotNull($value, "Light filter value missing for $id");
|
||||
self::assertLessThanOrEqual(15, $value, "Light filter value for $id is larger than the expected 15");
|
||||
self::assertGreaterThan(0, $value, "Light filter value for $id must be larger than 0");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user