Reduce memory footprint of state remapping tables

this becomes a significant problem when expanding metadata size.
This commit is contained in:
Dylan K. Taylor 2022-02-07 17:31:41 +00:00
parent 7a0f62ce5a
commit fe2c3d08a0
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -77,10 +77,16 @@ class BlockFactory{
private $fullList; private $fullList;
/** /**
* @var \SplFixedArray|int[] * @var int[]
* @phpstan-var \SplFixedArray<int> * @phpstan-var array<int, int>
*/ */
private \SplFixedArray $mappedStateIds; private array $defaultStateIndexes = [];
/**
* @var int[]
* @phpstan-var array<int, int>
*/
private array $mappedStateIndexes = [];
/** /**
* @var \SplFixedArray|int[] * @var \SplFixedArray|int[]
@ -105,7 +111,6 @@ class BlockFactory{
public function __construct(){ public function __construct(){
$this->fullList = new \SplFixedArray(1024 << Block::INTERNAL_METADATA_BITS); $this->fullList = new \SplFixedArray(1024 << Block::INTERNAL_METADATA_BITS);
$this->mappedStateIds = new \SplFixedArray(1024 << Block::INTERNAL_METADATA_BITS);
$this->light = \SplFixedArray::fromArray(array_fill(0, 1024 << Block::INTERNAL_METADATA_BITS, 0)); $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->lightFilter = \SplFixedArray::fromArray(array_fill(0, 1024 << Block::INTERNAL_METADATA_BITS, 1));
@ -944,11 +949,7 @@ class BlockFactory{
} }
foreach($ids as $id){ foreach($ids as $id){
for($meta = 0; $meta < 1 << Block::INTERNAL_METADATA_BITS; ++$meta){ $this->defaultStateIndexes[$id] = $default->getFullId();
if(!$this->isRegistered($id, $meta)){
$this->remap($id, $meta, $default);
}
}
} }
} }
@ -1027,8 +1028,12 @@ class BlockFactory{
} }
private function fillStaticArrays(int $index, Block $block) : void{ private function fillStaticArrays(int $index, Block $block) : void{
$this->fullList[$index] = $block; $fullId = $block->getFullId();
$this->mappedStateIds[$index] = $block->getFullId(); if($index !== $fullId){
$this->mappedStateIndexes[$index] = $fullId;
}else{
$this->fullList[$index] = $block;
}
$this->light[$index] = $block->getLightLevel(); $this->light[$index] = $block->getLightLevel();
$this->lightFilter[$index] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter $this->lightFilter[$index] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter
$this->blocksDirectSkyLight[$index] = $block->blocksDirectSkyLight(); $this->blocksDirectSkyLight[$index] = $block->blocksDirectSkyLight();
@ -1051,8 +1056,10 @@ class BlockFactory{
if($index < 0 || $index >= $this->fullList->getSize()){ if($index < 0 || $index >= $this->fullList->getSize()){
throw new \InvalidArgumentException("Block ID $id is out of bounds"); throw new \InvalidArgumentException("Block ID $id is out of bounds");
} }
if($this->fullList[$index] !== null){ if($this->fullList[$index] !== null){ //hot
$block = clone $this->fullList[$index]; $block = clone $this->fullList[$index];
}elseif(($mappedIndex = $this->getMappedStateId($index)) !== $index && $this->fullList[$mappedIndex] !== null){ //cold
$block = clone $this->fullList[$mappedIndex];
}else{ }else{
$block = new UnknownBlock(new BID($id, $meta), BlockBreakInfo::instant()); $block = new UnknownBlock(new BID($id, $meta), BlockBreakInfo::instant());
} }
@ -1068,7 +1075,15 @@ class BlockFactory{
* Returns whether a specified block state is already registered in the block factory. * Returns whether a specified block state is already registered in the block factory.
*/ */
public function isRegistered(int $id, int $meta = 0) : bool{ public function isRegistered(int $id, int $meta = 0) : bool{
$b = $this->fullList[($id << Block::INTERNAL_METADATA_BITS) | $meta]; $index = ($id << Block::INTERNAL_METADATA_BITS) | $meta;
$b = $this->fullList[$index];
if($b === null){
$mappedIndex = $this->mappedStateIndexes[$index] ?? $this->defaultStateIndexes[$id] ?? null;
if($mappedIndex === null){
return false;
}
$b = $this->fullList[$mappedIndex];
}
return $b !== null && !($b instanceof UnknownBlock); return $b !== null && !($b instanceof UnknownBlock);
} }
@ -1084,6 +1099,9 @@ class BlockFactory{
* Used to correct invalid blockstates found in loaded chunks. * Used to correct invalid blockstates found in loaded chunks.
*/ */
public function getMappedStateId(int $fullState) : int{ public function getMappedStateId(int $fullState) : int{
return $this->mappedStateIds[$fullState] ?? $fullState; if($this->fullList[$fullState] !== null){
return $fullState;
}
return $this->mappedStateIndexes[$fullState] ?? $this->defaultStateIndexes[$fullState >> Block::INTERNAL_METADATA_BITS] ?? $fullState;
} }
} }