mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-12 14:35:35 +00:00
RuntimeBlockStateRegistry: separate permutation expansion from register()
This commit is contained in:
parent
75f74454c6
commit
4c3892b2d6
@ -29,6 +29,7 @@ use pocketmine\data\runtime\InvalidSerializedRuntimeDataException;
|
|||||||
use pocketmine\utils\AssumptionFailedError;
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\utils\SingletonTrait;
|
use pocketmine\utils\SingletonTrait;
|
||||||
use pocketmine\world\light\LightUpdate;
|
use pocketmine\world\light\LightUpdate;
|
||||||
|
use function get_class;
|
||||||
use function min;
|
use function min;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,6 +82,34 @@ class RuntimeBlockStateRegistry{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates all the possible valid blockstates for a given block type.
|
||||||
|
*
|
||||||
|
* @phpstan-return \Generator<int, Block, void, void>
|
||||||
|
*/
|
||||||
|
private static function generateAllStatesForType(Block $block) : \Generator{
|
||||||
|
//TODO: this bruteforce approach to discovering all valid states is very inefficient for larger state data sizes
|
||||||
|
//at some point we'll need to find a better way to do this
|
||||||
|
$bits = $block->getRequiredTypeDataBits() + $block->getRequiredStateDataBits();
|
||||||
|
if($bits > Block::INTERNAL_STATE_DATA_BITS){
|
||||||
|
throw new \InvalidArgumentException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits");
|
||||||
|
}
|
||||||
|
for($stateData = 0; $stateData < (1 << $bits); ++$stateData){
|
||||||
|
$v = clone $block;
|
||||||
|
try{
|
||||||
|
$v->decodeStateData($stateData);
|
||||||
|
if($v->computeStateData() !== $stateData){
|
||||||
|
//TODO: this should probably be a hard error
|
||||||
|
throw new InvalidSerializedRuntimeDataException(get_class($block) . "::decodeStateData() accepts invalid state data (returned " . $v->computeStateData() . " for input $stateData)");
|
||||||
|
}
|
||||||
|
}catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a block type to its corresponding type ID. This is necessary for the block to be recognized when loading
|
* Maps a block type to its corresponding type ID. This is necessary for the block to be recognized when loading
|
||||||
* from disk, and also when being read at runtime.
|
* from disk, and also when being read at runtime.
|
||||||
@ -102,24 +131,7 @@ class RuntimeBlockStateRegistry{
|
|||||||
|
|
||||||
$this->typeIndex[$typeId] = clone $block;
|
$this->typeIndex[$typeId] = clone $block;
|
||||||
|
|
||||||
//TODO: this bruteforce approach to discovering all valid states is very inefficient for larger state data sizes
|
foreach(self::generateAllStatesForType($block) as $v){
|
||||||
//at some point we'll need to find a better way to do this
|
|
||||||
$bits = $block->getRequiredTypeDataBits() + $block->getRequiredStateDataBits();
|
|
||||||
if($bits > Block::INTERNAL_STATE_DATA_BITS){
|
|
||||||
throw new \InvalidArgumentException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits");
|
|
||||||
}
|
|
||||||
for($stateData = 0; $stateData < (1 << $bits); ++$stateData){
|
|
||||||
$v = clone $block;
|
|
||||||
try{
|
|
||||||
$v->decodeStateData($stateData);
|
|
||||||
if($v->computeStateData() !== $stateData){
|
|
||||||
//if the fullID comes back different, this is a broken state that we can't rely on; map it to default
|
|
||||||
throw new InvalidSerializedRuntimeDataException("Corrupted state");
|
|
||||||
}
|
|
||||||
}catch(InvalidSerializedRuntimeDataException $e){ //invalid property combination, leave it
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->fillStaticArrays($v->getStateId(), $v);
|
$this->fillStaticArrays($v->getStateId(), $v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user