mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-01 15:53:04 +00:00
Move block permutation generation into Block
this allows sealing off a whole bunch of internal APIs.
This commit is contained in:
parent
6c0ad9589b
commit
d4ca566fd0
@ -29,6 +29,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\block\tile\Spawnable;
|
use pocketmine\block\tile\Spawnable;
|
||||||
use pocketmine\block\tile\Tile;
|
use pocketmine\block\tile\Tile;
|
||||||
use pocketmine\block\utils\SupportType;
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\data\runtime\InvalidSerializedRuntimeDataException;
|
||||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||||
use pocketmine\data\runtime\RuntimeDataReader;
|
use pocketmine\data\runtime\RuntimeDataReader;
|
||||||
use pocketmine\data\runtime\RuntimeDataSizeCalculator;
|
use pocketmine\data\runtime\RuntimeDataSizeCalculator;
|
||||||
@ -185,14 +186,6 @@ class Block{
|
|||||||
return new ItemBlock($normalized);
|
return new ItemBlock($normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
final public function getRequiredTypeDataBits() : int{
|
|
||||||
return $this->requiredTypeDataBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
final public function getRequiredStateDataBits() : int{
|
|
||||||
return $this->requiredStateDataBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function decodeTypeData(int $data) : void{
|
private function decodeTypeData(int $data) : void{
|
||||||
$reader = new RuntimeDataReader($this->requiredTypeDataBits, $data);
|
$reader = new RuntimeDataReader($this->requiredTypeDataBits, $data);
|
||||||
|
|
||||||
@ -213,10 +206,7 @@ class Block{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function decodeTypeAndStateData(int $data) : void{
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
final public function decodeTypeAndStateData(int $data) : void{
|
|
||||||
$reader = new RuntimeDataReader($this->requiredTypeDataBits + $this->requiredStateDataBits, $data);
|
$reader = new RuntimeDataReader($this->requiredTypeDataBits + $this->requiredStateDataBits, $data);
|
||||||
$this->decodeTypeData($reader->readInt($this->requiredTypeDataBits));
|
$this->decodeTypeData($reader->readInt($this->requiredTypeDataBits));
|
||||||
$this->decodeStateData($reader->readInt($this->requiredStateDataBits));
|
$this->decodeStateData($reader->readInt($this->requiredStateDataBits));
|
||||||
@ -246,10 +236,7 @@ class Block{
|
|||||||
return $writer->getValue();
|
return $writer->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function computeTypeAndStateData() : int{
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
final public function computeTypeAndStateData() : int{
|
|
||||||
$writer = new RuntimeDataWriter($this->requiredTypeDataBits + $this->requiredStateDataBits);
|
$writer = new RuntimeDataWriter($this->requiredTypeDataBits + $this->requiredStateDataBits);
|
||||||
$writer->writeInt($this->requiredTypeDataBits, $this->computeTypeData());
|
$writer->writeInt($this->requiredTypeDataBits, $this->computeTypeData());
|
||||||
$writer->writeInt($this->requiredStateDataBits, $this->computeStateData());
|
$writer->writeInt($this->requiredStateDataBits, $this->computeStateData());
|
||||||
@ -281,6 +268,35 @@ class Block{
|
|||||||
//NOOP
|
//NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates copies of this Block in all possible state permutations.
|
||||||
|
* Every possible combination of known properties (e.g. facing, open/closed, powered/unpowered, on/off) will be
|
||||||
|
* generated.
|
||||||
|
*
|
||||||
|
* @phpstan-return \Generator<int, Block, void, void>
|
||||||
|
*/
|
||||||
|
public function generateStatePermutations() : \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 = $this->requiredTypeDataBits + $this->requiredStateDataBits;
|
||||||
|
if($bits > Block::INTERNAL_STATE_DATA_BITS){
|
||||||
|
throw new \LogicException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits");
|
||||||
|
}
|
||||||
|
for($stateData = 0; $stateData < (1 << $bits); ++$stateData){
|
||||||
|
$v = clone $this;
|
||||||
|
try{
|
||||||
|
$v->decodeTypeAndStateData($stateData);
|
||||||
|
if($v->computeTypeAndStateData() !== $stateData){
|
||||||
|
throw new \LogicException(static::class . "::decodeStateData() accepts invalid state data (returned " . $v->computeTypeAndStateData() . " for input $stateData)");
|
||||||
|
}
|
||||||
|
}catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when this block is created, set, or has a neighbouring block update, to re-detect dynamic properties which
|
* Called when this block is created, set, or has a neighbouring block update, to re-detect dynamic properties which
|
||||||
* are not saved on the world.
|
* are not saved on the world.
|
||||||
|
@ -25,11 +25,9 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\BlockBreakInfo as BreakInfo;
|
use pocketmine\block\BlockBreakInfo as BreakInfo;
|
||||||
use pocketmine\block\BlockIdentifier as BID;
|
use pocketmine\block\BlockIdentifier as BID;
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,33 +80,6 @@ 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->decodeTypeAndStateData($stateData);
|
|
||||||
if($v->computeTypeAndStateData() !== $stateData){
|
|
||||||
throw new \LogicException(get_class($block) . "::decodeStateData() accepts invalid state data (returned " . $v->computeTypeAndStateData() . " 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.
|
||||||
@ -130,7 +101,7 @@ class RuntimeBlockStateRegistry{
|
|||||||
|
|
||||||
$this->typeIndex[$typeId] = clone $block;
|
$this->typeIndex[$typeId] = clone $block;
|
||||||
|
|
||||||
foreach(self::generateAllStatesForType($block) as $v){
|
foreach($block->generateStatePermutations() as $v){
|
||||||
$this->fillStaticArrays($v->getStateId(), $v);
|
$this->fillStaticArrays($v->getStateId(), $v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ class BlockTest extends TestCase{
|
|||||||
|
|
||||||
$states = $this->blockFactory->getAllKnownStates();
|
$states = $this->blockFactory->getAllKnownStates();
|
||||||
foreach($states as $stateId => $state){
|
foreach($states as $stateId => $state){
|
||||||
self::assertArrayHasKey($stateId, $knownStates, "New block state $stateId (" . $state->getTypeId() . ":" . $state->computeTypeAndStateData() . ", " . print_r($state, true) . ") - consistency check may need regenerating");
|
self::assertArrayHasKey($stateId, $knownStates, "New block state $stateId (" . print_r($state, true) . ") - consistency check may need regenerating");
|
||||||
self::assertSame($knownStates[$stateId], $state->getName());
|
self::assertSame($knownStates[$stateId], $state->getName());
|
||||||
}
|
}
|
||||||
asort($knownStates, SORT_STRING);
|
asort($knownStates, SORT_STRING);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user