Block: Get rid of state bitmasks

This story dates back to the days when getVariantBitmask() was introduced. The purpose of this function was to allow the variant info to be extracted from the metadata, for use with item drops. This was later changed to state bitmask for reasons I don't clearly recall.
In the great 4.0 refactor, we now store variant magic numbers separately, so we don't need any generic bitmask to split up variant and state information anymore. Variant is now only ever serialized and never deserialized. The same thing goes for blockIDs. States are read from the world by matching the full stateID against a table of prefilled known blocks, so the variant doesn't need to be deserialized - only the state does, and the state metadata readers already do bit fuckery by themselves and don't need this mask - notice how little actual changes were required to get rid of this?
This commit is contained in:
Dylan K. Taylor 2019-02-24 14:42:53 +00:00
parent 023fecabac
commit b7b05e729e
53 changed files with 10 additions and 247 deletions

View File

@ -50,11 +50,7 @@ class Anvil extends Transparent implements Fallable{
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataValidator::readLegacyHorizontalFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b11;
$this->facing = BlockDataValidator::readLegacyHorizontalFacing($stateMeta & 0x03);
}
public function getHardness() : float{

View File

@ -95,10 +95,6 @@ abstract class BaseRail extends Flowable{
$this->connections = $connections;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 0.7;
}

View File

@ -68,10 +68,6 @@ class Bed extends Transparent{
$this->head = ($stateMeta & self::BITFLAG_HEAD) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
//read extra state information from the tile - this is an ugly hack

View File

@ -43,8 +43,6 @@ use pocketmine\Player;
use pocketmine\plugin\Plugin;
use pocketmine\tile\TileFactory;
use function array_merge;
use function assert;
use function dechex;
use function get_class;
use const PHP_INT_MAX;
@ -82,9 +80,6 @@ class Block extends Position implements BlockIds, Metadatable{
* @param string $name English name of the block type (TODO: implement translations)
*/
public function __construct(BlockIdentifier $idInfo, string $name){
if(($idInfo->getVariant() & $this->getStateBitmask()) !== 0){
throw new \InvalidArgumentException("Variant 0x" . dechex($idInfo->getVariant()) . " collides with state bitmask 0x" . dechex($this->getStateBitmask()));
}
$this->idInfo = $idInfo;
$this->fallbackName = $name;
}
@ -123,9 +118,7 @@ class Block extends Position implements BlockIds, Metadatable{
* @return int
*/
public function getDamage() : int{
$stateMeta = $this->writeStateToMeta();
assert(($stateMeta & ~$this->getStateBitmask()) === 0);
return $this->idInfo->getVariant() | $stateMeta;
return $this->idInfo->getVariant() | $this->writeStateToMeta();
}
protected function writeStateToMeta() : int{
@ -168,15 +161,6 @@ class Block extends Position implements BlockIds, Metadatable{
}
}
/**
* Returns a bitmask used to extract state bits from block metadata.
*
* @return int
*/
public function getStateBitmask() : int{
return 0;
}
/**
* Returns whether the given block has an equivalent type to this one. This compares base legacy ID and variant.
*

View File

@ -527,32 +527,13 @@ class BlockFactory{
* $override parameter.
*/
public static function register(Block $block, bool $override = false) : void{
$variant = $block->getIdInfo()->getVariant();
$stateMask = $block->getStateBitmask();
if(($variant & $stateMask) !== 0){
throw new \InvalidArgumentException("Block variant collides with state bitmask");
}
foreach($block->getIdInfo()->getAllBlockIds() as $id){
if(!$override and self::isRegistered($id, $variant)){
throw new \InvalidArgumentException("Block registration $id:$variant conflicts with an existing block");
}
for($m = $variant; $m <= ($variant | $stateMask); ++$m){
if(($m & ~$stateMask) !== $variant){
continue;
}
if(!$override and self::isRegistered($id, $m)){
throw new \InvalidArgumentException("Block registration " . get_class($block) . " has states which conflict with other blocks");
}
for($m = 0; $m < 16; ++$m){
$index = ($id << 4) | $m;
$v = clone $block;
try{
$v->readStateFromData($id, $m & $stateMask);
$v->readStateFromData($id, $m);
if($v->getDamage() !== $m){
throw new InvalidBlockStateException("Corrupted meta"); //don't register anything that isn't the same when we read it back again
}
@ -560,9 +541,14 @@ class BlockFactory{
continue;
}
if(!$override and self::isRegistered($id, $m)){
throw new \InvalidArgumentException("Block registration " . get_class($block) . " has states which conflict with other blocks");
}
self::fillStaticArrays($index, $v);
}
$variant = $block->getIdInfo()->getVariant();
if(!self::isRegistered($id, $variant)){
self::fillStaticArrays(($id << 4) | $variant, $block); //register default state mapped to variant, for blocks which don't use 0 as valid state
}

View File

@ -44,10 +44,6 @@ class BrewingStand extends Transparent{
$this->northwestSlot = ($stateMeta & 0x04) !== 0;
}
public function getStateBitmask() : int{
return 0b111;
}
public function getHardness() : float{
return 0.5;
}

View File

@ -47,10 +47,6 @@ abstract class Button extends Flowable{
$this->powered = ($stateMeta & 0x08) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
//TODO: check valid target block
$this->facing = $face;

View File

@ -47,10 +47,6 @@ class Cactus extends Transparent{
$this->age = BlockDataValidator::readBoundedInt("age", $stateMeta, 0, 15);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 0.4;
}

View File

@ -46,10 +46,6 @@ class Cake extends Transparent implements FoodSource{
$this->bites = BlockDataValidator::readBoundedInt("bites", $stateMeta, 0, 6);
}
public function getStateBitmask() : int{
return 0b111;
}
public function getHardness() : float{
return 0.5;
}

View File

@ -44,10 +44,6 @@ class Chest extends Transparent{
$this->facing = BlockDataValidator::readHorizontalFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function getHardness() : float{
return 2.5;
}

View File

@ -51,10 +51,6 @@ class CocoaBlock extends Transparent{
$this->age = BlockDataValidator::readBoundedInt("age", $stateMeta >> 2, 0, 2);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 0.2;
}

View File

@ -44,10 +44,6 @@ abstract class Crops extends Flowable{
$this->age = BlockDataValidator::readBoundedInt("age", $stateMeta, 0, 7);
}
public function getStateBitmask() : int{
return 0b111;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace->getSide(Facing::DOWN)->getId() === Block::FARMLAND){
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);

View File

@ -57,10 +57,6 @@ class DaylightSensor extends Transparent{
$this->inverted = $id === $this->idInfo->getSecondId();
}
public function getStateBitmask() : int{
return 0b1111;
}
public function isInverted() : bool{
return $this->inverted;
}

View File

@ -67,10 +67,6 @@ abstract class Door extends Transparent{
}
}
public function getStateBitmask() : int{
return 0b1111;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();

View File

@ -43,10 +43,6 @@ class DoublePlant extends Flowable{
$this->top = ($stateMeta & self::BITFLAG_TOP) !== 0;
}
public function getStateBitmask() : int{
return 0b1000;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$id = $blockReplace->getSide(Facing::DOWN)->getId();
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Facing::UP)->canBeReplaced()){

View File

@ -47,10 +47,6 @@ class EndPortalFrame extends Solid{
$this->eye = ($stateMeta & 0x04) !== 0;
}
public function getStateBitmask() : int{
return 0b111;
}
public function getLightLevel() : int{
return 1;
}

View File

@ -50,10 +50,6 @@ class EndRod extends Flowable{
$this->facing = BlockDataValidator::readFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
if($blockClicked instanceof EndRod and $blockClicked->facing === $this->facing){

View File

@ -42,10 +42,6 @@ class Farmland extends Transparent{
$this->wetness = BlockDataValidator::readBoundedInt("wetness", $stateMeta, 0, 7);
}
public function getStateBitmask() : int{
return 0b111;
}
public function getHardness() : float{
return 0.6;
}

View File

@ -50,10 +50,6 @@ class FenceGate extends Transparent{
$this->inWall = ($stateMeta & 0x08) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 2;
}

View File

@ -48,10 +48,6 @@ class Fire extends Flowable{
$this->age = BlockDataValidator::readBoundedInt("age", $stateMeta, 0, 15);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function hasEntityCollision() : bool{
return true;
}

View File

@ -43,10 +43,6 @@ class FlowerPot extends Flowable{
$this->occupied = $stateMeta !== 0;
}
public function getStateBitmask() : int{
return 0b1111; //vanilla uses various values, we only care about 1 and 0 for PE
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return AxisAlignedBB::one()->contract(3 / 16, 0, 3 / 16)->trim(Facing::UP, 5 / 8);
}

View File

@ -53,10 +53,6 @@ class Furnace extends Solid{
$this->lit = $id === $this->idInfo->getSecondId();
}
public function getStateBitmask() : int{
return 0b111;
}
public function getHardness() : float{
return 3.5;
}

View File

@ -44,10 +44,6 @@ class GlazedTerracotta extends Solid{
$this->facing = BlockDataValidator::readHorizontalFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function getHardness() : float{
return 1.4;
}

View File

@ -77,10 +77,6 @@ class ItemFrame extends Flowable{
}
}
public function getStateBitmask() : int{
return 0b111;
}
/**
* @return int
*/

View File

@ -44,10 +44,6 @@ class Ladder extends Transparent{
$this->facing = BlockDataValidator::readHorizontalFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function hasEntityCollision() : bool{
return true;
}

View File

@ -56,10 +56,6 @@ class Leaves extends Transparent{
$this->checkDecay = ($stateMeta & 0x08) !== 0;
}
public function getStateBitmask() : int{
return 0b1100;
}
public function getHardness() : float{
return 0.2;
}

View File

@ -69,10 +69,6 @@ class Lever extends Flowable{
$this->powered = ($stateMeta & 0x08) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 0.5;
}

View File

@ -77,10 +77,6 @@ abstract class Liquid extends Transparent{
$this->still = $id === $this->idInfo->getSecondId();
}
public function getStateBitmask() : int{
return 0b1111;
}
public function hasEntityCollision() : bool{
return true;
}

View File

@ -44,10 +44,6 @@ class NetherReactor extends Solid{
$this->state = BlockDataValidator::readBoundedInt("state", $stateMeta, 0, 2);
}
public function getStateBitmask() : int{
return 0b11;
}
public function getToolType() : int{
return BlockToolType::TYPE_PICKAXE;
}

View File

@ -45,10 +45,6 @@ class NetherWartPlant extends Flowable{
$this->age = BlockDataValidator::readBoundedInt("age", $stateMeta, 0, 3);
}
public function getStateBitmask() : int{
return 0b11;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if($down->getId() === Block::SOUL_SAND){

View File

@ -43,10 +43,6 @@ class Pumpkin extends Solid{
return Bearing::fromFacing($this->facing);
}
public function getStateBitmask() : int{
return 0b11;
}
public function getHardness() : float{
return 1;
}

View File

@ -45,10 +45,6 @@ class RedMushroomBlock extends Solid{
$this->rotationData = $stateMeta;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 0.2;
}

View File

@ -60,10 +60,6 @@ class RedstoneRepeater extends Flowable{
return Bearing::fromFacing($this->facing) | (($this->delay - 1) << 2);
}
public function getStateBitmask() : int{
return 0b1111;
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return AxisAlignedBB::one()->trim(Facing::UP, 7 / 8);
}

View File

@ -38,10 +38,6 @@ class RedstoneWire extends Flowable{
return $this->power;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
//TODO: check connections to nearby redstone components

View File

@ -53,10 +53,6 @@ class Sapling extends Flowable{
$this->ready = ($stateMeta & 0x08) !== 0;
}
public function getStateBitmask() : int{
return 0b1000;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::FARMLAND){

View File

@ -43,10 +43,6 @@ class SignPost extends Transparent{
$this->rotation = $stateMeta;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 1;
}

View File

@ -35,8 +35,4 @@ abstract class SimplePressurePlate extends PressurePlate{
public function readStateFromData(int $id, int $stateMeta) : void{
$this->powered = $stateMeta !== 0;
}
public function getStateBitmask() : int{
return 0b1;
}
}

View File

@ -50,10 +50,6 @@ class Skull extends Flowable{
$this->facing = $stateMeta === 1 ? Facing::UP : BlockDataValidator::readHorizontalFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
$tile = $this->level->getTile($this);

View File

@ -61,10 +61,6 @@ abstract class Slab extends Transparent{
}
}
public function getStateBitmask() : int{
return 0b1000;
}
public function isTransparent() : bool{
return $this->slabType !== SlabType::DOUBLE();
}

View File

@ -50,10 +50,6 @@ class SnowLayer extends Flowable implements Fallable{
$this->layers = BlockDataValidator::readBoundedInt("layers", $stateMeta + 1, 1, 8);
}
public function getStateBitmask() : int{
return 0b111;
}
public function canBeReplaced() : bool{
return $this->layers < 8;
}

View File

@ -37,10 +37,6 @@ class Sponge extends Solid{
$this->wet = $stateMeta !== 0;
}
public function getStateBitmask() : int{
return 0b1;
}
public function getHardness() : float{
return 0.6;
}

View File

@ -53,10 +53,6 @@ abstract class Stair extends Transparent{
$this->upsideDown = ($stateMeta & 0x04) !== 0;
}
public function getStateBitmask() : int{
return 0b111;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();

View File

@ -46,10 +46,6 @@ class StandingBanner extends Transparent{
$this->rotation = $stateMeta;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 1;
}

View File

@ -44,10 +44,6 @@ class Sugarcane extends Flowable{
$this->age = BlockDataValidator::readBoundedInt("age", $stateMeta, 0, 15);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function onActivate(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Fertilizer){
if($this->getSide(Facing::DOWN)->getId() !== self::SUGARCANE_BLOCK){

View File

@ -39,13 +39,10 @@ class Torch extends Flowable{
}
public function readStateFromData(int $id, int $stateMeta) : void{
$stateMeta &= 0x07;
$this->facing = $stateMeta === 5 ? Facing::UP : BlockDataValidator::readHorizontalFacing(6 - $stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function getLightLevel() : int{
return 14;
}

View File

@ -54,10 +54,6 @@ class Trapdoor extends Transparent{
$this->open = ($stateMeta & self::MASK_OPENED) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getHardness() : float{
return 3;
}

View File

@ -45,10 +45,6 @@ class Tripwire extends Flowable{
$this->disarmed = ($stateMeta & 0x08) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function isAffectedBySilkTouch() : bool{
return false;
}

View File

@ -49,10 +49,6 @@ class TripwireHook extends Flowable{
$this->powered = ($stateMeta & 0x08) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(Facing::axis($face) !== Facing::AXIS_Y){
//TODO: check face is valid

View File

@ -57,10 +57,6 @@ class Vine extends Flowable{
$this->setFaceFromMeta($stateMeta, self::FLAG_EAST, Facing::EAST);
}
public function getStateBitmask() : int{
return 0b1111;
}
private function setFaceFromMeta(int $meta, int $flag, int $face) : void{
if(($meta & $flag) !== 0){
$this->faces[$face] = true;

View File

@ -39,10 +39,6 @@ class WallBanner extends StandingBanner{
$this->facing = BlockDataValidator::readHorizontalFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::opposite($this->facing))->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);

View File

@ -39,10 +39,6 @@ class WallSign extends SignPost{
$this->facing = BlockDataValidator::readHorizontalFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::opposite($this->facing))->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);

View File

@ -37,8 +37,4 @@ abstract class WeightedPressurePlate extends PressurePlate{
public function readStateFromData(int $id, int $stateMeta) : void{
$this->power = BlockDataValidator::readBoundedInt("power", $stateMeta, 0, 15);
}
public function getStateBitmask() : int{
return 0b1111;
}
}

View File

@ -52,14 +52,6 @@ trait PillarRotationTrait{
$this->readAxisFromMeta($stateMeta);
}
/**
* @see Block::getStateBitmask()
* @return int
*/
public function getStateBitmask() : int{
return 0b1100;
}
protected function readAxisFromMeta(int $meta) : void{
static $map = [
0 => Facing::AXIS_Y,