diff --git a/src/pocketmine/block/Anvil.php b/src/pocketmine/block/Anvil.php index dc81bcc078..23ad43911e 100644 --- a/src/pocketmine/block/Anvil.php +++ b/src/pocketmine/block/Anvil.php @@ -50,7 +50,11 @@ class Anvil extends Transparent implements Fallable{ } public function readStateFromData(int $id, int $stateMeta) : void{ - $this->facing = BlockDataValidator::readLegacyHorizontalFacing($stateMeta & 0x03); + $this->facing = BlockDataValidator::readLegacyHorizontalFacing($stateMeta); + } + + public function getStateBitmask() : int{ + return 0b11; } public function getHardness() : float{ diff --git a/src/pocketmine/block/BaseRail.php b/src/pocketmine/block/BaseRail.php index 6fb66260fd..3dfb543ed9 100644 --- a/src/pocketmine/block/BaseRail.php +++ b/src/pocketmine/block/BaseRail.php @@ -95,6 +95,10 @@ abstract class BaseRail extends Flowable{ $this->connections = $connections; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function getHardness() : float{ return 0.7; } diff --git a/src/pocketmine/block/Bed.php b/src/pocketmine/block/Bed.php index 74b245c516..da51227e70 100644 --- a/src/pocketmine/block/Bed.php +++ b/src/pocketmine/block/Bed.php @@ -68,6 +68,10 @@ 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 diff --git a/src/pocketmine/block/Block.php b/src/pocketmine/block/Block.php index 4f63c4f72e..fb1deb2469 100644 --- a/src/pocketmine/block/Block.php +++ b/src/pocketmine/block/Block.php @@ -43,6 +43,8 @@ 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; @@ -80,6 +82,9 @@ 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; } @@ -118,7 +123,9 @@ class Block extends Position implements BlockIds, Metadatable{ * @return int */ public function getDamage() : int{ - return $this->idInfo->getVariant() | $this->writeStateToMeta(); + $stateMeta = $this->writeStateToMeta(); + assert(($stateMeta & ~$this->getStateBitmask()) === 0); + return $this->idInfo->getVariant() | $stateMeta; } protected function writeStateToMeta() : int{ @@ -161,6 +168,15 @@ 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. * diff --git a/src/pocketmine/block/BlockFactory.php b/src/pocketmine/block/BlockFactory.php index 818a124575..825567fef8 100644 --- a/src/pocketmine/block/BlockFactory.php +++ b/src/pocketmine/block/BlockFactory.php @@ -527,17 +527,20 @@ class BlockFactory{ * $override parameter. */ public static function register(Block $block, bool $override = false) : void{ - foreach($block->getIdInfo()->getAllBlockIds() as $id){ - for($m = 0; $m < 16; ++$m){ - $index = ($id << 4) | $m; + $variant = $block->getIdInfo()->getVariant(); - $v = clone $block; - try{ - $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 - } - }catch(InvalidBlockStateException $e){ //invalid property combination + $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; } @@ -545,10 +548,21 @@ class BlockFactory{ throw new \InvalidArgumentException("Block registration " . get_class($block) . " has states which conflict with other blocks"); } + $index = ($id << 4) | $m; + + $v = clone $block; + try{ + $v->readStateFromData($id, $m & $stateMask); + if($v->getDamage() !== $m){ + throw new InvalidBlockStateException("Corrupted meta"); //don't register anything that isn't the same when we read it back again + } + }catch(InvalidBlockStateException $e){ //invalid property combination + continue; + } + 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 } diff --git a/src/pocketmine/block/BrewingStand.php b/src/pocketmine/block/BrewingStand.php index 775b2ba008..f9833823b1 100644 --- a/src/pocketmine/block/BrewingStand.php +++ b/src/pocketmine/block/BrewingStand.php @@ -44,6 +44,10 @@ class BrewingStand extends Transparent{ $this->northwestSlot = ($stateMeta & 0x04) !== 0; } + public function getStateBitmask() : int{ + return 0b111; + } + public function getHardness() : float{ return 0.5; } diff --git a/src/pocketmine/block/Button.php b/src/pocketmine/block/Button.php index b05f94e7ae..1ff2484147 100644 --- a/src/pocketmine/block/Button.php +++ b/src/pocketmine/block/Button.php @@ -47,6 +47,10 @@ 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; diff --git a/src/pocketmine/block/Cactus.php b/src/pocketmine/block/Cactus.php index 381c96174f..dcf9655200 100644 --- a/src/pocketmine/block/Cactus.php +++ b/src/pocketmine/block/Cactus.php @@ -47,6 +47,10 @@ 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; } diff --git a/src/pocketmine/block/Cake.php b/src/pocketmine/block/Cake.php index 0e98fa117f..335f0f6447 100644 --- a/src/pocketmine/block/Cake.php +++ b/src/pocketmine/block/Cake.php @@ -46,6 +46,10 @@ 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; } diff --git a/src/pocketmine/block/Chest.php b/src/pocketmine/block/Chest.php index 4c18414cfd..757e67c3dc 100644 --- a/src/pocketmine/block/Chest.php +++ b/src/pocketmine/block/Chest.php @@ -44,6 +44,10 @@ class Chest extends Transparent{ $this->facing = BlockDataValidator::readHorizontalFacing($stateMeta); } + public function getStateBitmask() : int{ + return 0b111; + } + public function getHardness() : float{ return 2.5; } diff --git a/src/pocketmine/block/CocoaBlock.php b/src/pocketmine/block/CocoaBlock.php index 46c654c791..0046d27aab 100644 --- a/src/pocketmine/block/CocoaBlock.php +++ b/src/pocketmine/block/CocoaBlock.php @@ -51,6 +51,10 @@ 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; } diff --git a/src/pocketmine/block/Crops.php b/src/pocketmine/block/Crops.php index 45f49b74b3..2586d9109e 100644 --- a/src/pocketmine/block/Crops.php +++ b/src/pocketmine/block/Crops.php @@ -44,6 +44,10 @@ 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); diff --git a/src/pocketmine/block/DaylightSensor.php b/src/pocketmine/block/DaylightSensor.php index c6806f98c3..a379c5f146 100644 --- a/src/pocketmine/block/DaylightSensor.php +++ b/src/pocketmine/block/DaylightSensor.php @@ -57,6 +57,10 @@ class DaylightSensor extends Transparent{ $this->inverted = $id === $this->idInfo->getSecondId(); } + public function getStateBitmask() : int{ + return 0b1111; + } + public function isInverted() : bool{ return $this->inverted; } diff --git a/src/pocketmine/block/Door.php b/src/pocketmine/block/Door.php index ac9d689f5f..39e56e5f8c 100644 --- a/src/pocketmine/block/Door.php +++ b/src/pocketmine/block/Door.php @@ -67,6 +67,10 @@ abstract class Door extends Transparent{ } } + public function getStateBitmask() : int{ + return 0b1111; + } + public function readStateFromWorld() : void{ parent::readStateFromWorld(); diff --git a/src/pocketmine/block/DoublePlant.php b/src/pocketmine/block/DoublePlant.php index 3b4151890a..a9dd48ee0f 100644 --- a/src/pocketmine/block/DoublePlant.php +++ b/src/pocketmine/block/DoublePlant.php @@ -43,6 +43,10 @@ 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()){ diff --git a/src/pocketmine/block/EndPortalFrame.php b/src/pocketmine/block/EndPortalFrame.php index 53b7cc73f6..aebdc7b477 100644 --- a/src/pocketmine/block/EndPortalFrame.php +++ b/src/pocketmine/block/EndPortalFrame.php @@ -47,6 +47,10 @@ class EndPortalFrame extends Solid{ $this->eye = ($stateMeta & 0x04) !== 0; } + public function getStateBitmask() : int{ + return 0b111; + } + public function getLightLevel() : int{ return 1; } diff --git a/src/pocketmine/block/EndRod.php b/src/pocketmine/block/EndRod.php index 03f7622722..1290815382 100644 --- a/src/pocketmine/block/EndRod.php +++ b/src/pocketmine/block/EndRod.php @@ -50,6 +50,10 @@ 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){ diff --git a/src/pocketmine/block/Farmland.php b/src/pocketmine/block/Farmland.php index 022bde450d..32d9079907 100644 --- a/src/pocketmine/block/Farmland.php +++ b/src/pocketmine/block/Farmland.php @@ -42,6 +42,10 @@ 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; } diff --git a/src/pocketmine/block/FenceGate.php b/src/pocketmine/block/FenceGate.php index 0526b36897..b26152064e 100644 --- a/src/pocketmine/block/FenceGate.php +++ b/src/pocketmine/block/FenceGate.php @@ -50,6 +50,10 @@ class FenceGate extends Transparent{ $this->inWall = ($stateMeta & 0x08) !== 0; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function getHardness() : float{ return 2; } diff --git a/src/pocketmine/block/Fire.php b/src/pocketmine/block/Fire.php index 5e79668b3b..faa722df4e 100644 --- a/src/pocketmine/block/Fire.php +++ b/src/pocketmine/block/Fire.php @@ -48,6 +48,10 @@ class Fire extends Flowable{ $this->age = BlockDataValidator::readBoundedInt("age", $stateMeta, 0, 15); } + public function getStateBitmask() : int{ + return 0b1111; + } + public function hasEntityCollision() : bool{ return true; } diff --git a/src/pocketmine/block/FlowerPot.php b/src/pocketmine/block/FlowerPot.php index 297fe13361..057827e65c 100644 --- a/src/pocketmine/block/FlowerPot.php +++ b/src/pocketmine/block/FlowerPot.php @@ -43,6 +43,10 @@ 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); } diff --git a/src/pocketmine/block/Furnace.php b/src/pocketmine/block/Furnace.php index 595f2c1097..a407aa75d4 100644 --- a/src/pocketmine/block/Furnace.php +++ b/src/pocketmine/block/Furnace.php @@ -53,6 +53,10 @@ class Furnace extends Solid{ $this->lit = $id === $this->idInfo->getSecondId(); } + public function getStateBitmask() : int{ + return 0b111; + } + public function getHardness() : float{ return 3.5; } diff --git a/src/pocketmine/block/GlazedTerracotta.php b/src/pocketmine/block/GlazedTerracotta.php index 173d17d9ef..a3f4957ba9 100644 --- a/src/pocketmine/block/GlazedTerracotta.php +++ b/src/pocketmine/block/GlazedTerracotta.php @@ -44,6 +44,10 @@ class GlazedTerracotta extends Solid{ $this->facing = BlockDataValidator::readHorizontalFacing($stateMeta); } + public function getStateBitmask() : int{ + return 0b111; + } + public function getHardness() : float{ return 1.4; } diff --git a/src/pocketmine/block/ItemFrame.php b/src/pocketmine/block/ItemFrame.php index 7faef10528..68891072db 100644 --- a/src/pocketmine/block/ItemFrame.php +++ b/src/pocketmine/block/ItemFrame.php @@ -77,6 +77,10 @@ class ItemFrame extends Flowable{ } } + public function getStateBitmask() : int{ + return 0b111; + } + /** * @return int */ diff --git a/src/pocketmine/block/Ladder.php b/src/pocketmine/block/Ladder.php index 9d9c38b9df..e5589279e9 100644 --- a/src/pocketmine/block/Ladder.php +++ b/src/pocketmine/block/Ladder.php @@ -44,6 +44,10 @@ class Ladder extends Transparent{ $this->facing = BlockDataValidator::readHorizontalFacing($stateMeta); } + public function getStateBitmask() : int{ + return 0b111; + } + public function hasEntityCollision() : bool{ return true; } diff --git a/src/pocketmine/block/Leaves.php b/src/pocketmine/block/Leaves.php index 41ba257f7e..563f378e3b 100644 --- a/src/pocketmine/block/Leaves.php +++ b/src/pocketmine/block/Leaves.php @@ -56,6 +56,10 @@ class Leaves extends Transparent{ $this->checkDecay = ($stateMeta & 0x08) !== 0; } + public function getStateBitmask() : int{ + return 0b1100; + } + public function getHardness() : float{ return 0.2; } diff --git a/src/pocketmine/block/Lever.php b/src/pocketmine/block/Lever.php index 0221a30ac0..458fb89329 100644 --- a/src/pocketmine/block/Lever.php +++ b/src/pocketmine/block/Lever.php @@ -69,6 +69,10 @@ class Lever extends Flowable{ $this->powered = ($stateMeta & 0x08) !== 0; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function getHardness() : float{ return 0.5; } diff --git a/src/pocketmine/block/Liquid.php b/src/pocketmine/block/Liquid.php index 3be306f145..cb98b7ca83 100644 --- a/src/pocketmine/block/Liquid.php +++ b/src/pocketmine/block/Liquid.php @@ -77,6 +77,10 @@ abstract class Liquid extends Transparent{ $this->still = $id === $this->idInfo->getSecondId(); } + public function getStateBitmask() : int{ + return 0b1111; + } + public function hasEntityCollision() : bool{ return true; } diff --git a/src/pocketmine/block/NetherReactor.php b/src/pocketmine/block/NetherReactor.php index b7cd4eab53..3a90117e83 100644 --- a/src/pocketmine/block/NetherReactor.php +++ b/src/pocketmine/block/NetherReactor.php @@ -44,6 +44,10 @@ 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; } diff --git a/src/pocketmine/block/NetherWartPlant.php b/src/pocketmine/block/NetherWartPlant.php index 7c7461af1c..f0027de2a9 100644 --- a/src/pocketmine/block/NetherWartPlant.php +++ b/src/pocketmine/block/NetherWartPlant.php @@ -45,6 +45,10 @@ 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){ diff --git a/src/pocketmine/block/Pumpkin.php b/src/pocketmine/block/Pumpkin.php index 58e604463d..0f760987fd 100644 --- a/src/pocketmine/block/Pumpkin.php +++ b/src/pocketmine/block/Pumpkin.php @@ -43,6 +43,10 @@ class Pumpkin extends Solid{ return Bearing::fromFacing($this->facing); } + public function getStateBitmask() : int{ + return 0b11; + } + public function getHardness() : float{ return 1; } diff --git a/src/pocketmine/block/RedMushroomBlock.php b/src/pocketmine/block/RedMushroomBlock.php index 166e5cb4ee..7e2bbf48ea 100644 --- a/src/pocketmine/block/RedMushroomBlock.php +++ b/src/pocketmine/block/RedMushroomBlock.php @@ -45,6 +45,10 @@ class RedMushroomBlock extends Solid{ $this->rotationData = $stateMeta; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function getHardness() : float{ return 0.2; } diff --git a/src/pocketmine/block/RedstoneRepeater.php b/src/pocketmine/block/RedstoneRepeater.php index d48926e5e1..ab16eead22 100644 --- a/src/pocketmine/block/RedstoneRepeater.php +++ b/src/pocketmine/block/RedstoneRepeater.php @@ -60,6 +60,10 @@ 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); } diff --git a/src/pocketmine/block/RedstoneWire.php b/src/pocketmine/block/RedstoneWire.php index 677f0b3a4f..6f95e906b4 100644 --- a/src/pocketmine/block/RedstoneWire.php +++ b/src/pocketmine/block/RedstoneWire.php @@ -38,6 +38,10 @@ 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 diff --git a/src/pocketmine/block/Sapling.php b/src/pocketmine/block/Sapling.php index 80e82b7507..0b725ffab8 100644 --- a/src/pocketmine/block/Sapling.php +++ b/src/pocketmine/block/Sapling.php @@ -53,6 +53,10 @@ 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){ diff --git a/src/pocketmine/block/SignPost.php b/src/pocketmine/block/SignPost.php index 53f3331027..1470fea51a 100644 --- a/src/pocketmine/block/SignPost.php +++ b/src/pocketmine/block/SignPost.php @@ -43,6 +43,10 @@ class SignPost extends Transparent{ $this->rotation = $stateMeta; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function getHardness() : float{ return 1; } diff --git a/src/pocketmine/block/SimplePressurePlate.php b/src/pocketmine/block/SimplePressurePlate.php index 79205d5d59..7ffb9a7748 100644 --- a/src/pocketmine/block/SimplePressurePlate.php +++ b/src/pocketmine/block/SimplePressurePlate.php @@ -35,4 +35,8 @@ abstract class SimplePressurePlate extends PressurePlate{ public function readStateFromData(int $id, int $stateMeta) : void{ $this->powered = $stateMeta !== 0; } + + public function getStateBitmask() : int{ + return 0b1; + } } diff --git a/src/pocketmine/block/Skull.php b/src/pocketmine/block/Skull.php index 4de79e1f0e..da62c2c26d 100644 --- a/src/pocketmine/block/Skull.php +++ b/src/pocketmine/block/Skull.php @@ -50,6 +50,10 @@ 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); diff --git a/src/pocketmine/block/Slab.php b/src/pocketmine/block/Slab.php index 078c39bf35..dd7599972f 100644 --- a/src/pocketmine/block/Slab.php +++ b/src/pocketmine/block/Slab.php @@ -61,6 +61,10 @@ abstract class Slab extends Transparent{ } } + public function getStateBitmask() : int{ + return 0b1000; + } + public function isTransparent() : bool{ return $this->slabType !== SlabType::DOUBLE(); } diff --git a/src/pocketmine/block/SnowLayer.php b/src/pocketmine/block/SnowLayer.php index ff9ff49b91..e80b18cf82 100644 --- a/src/pocketmine/block/SnowLayer.php +++ b/src/pocketmine/block/SnowLayer.php @@ -50,6 +50,10 @@ 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; } diff --git a/src/pocketmine/block/Sponge.php b/src/pocketmine/block/Sponge.php index 402f938f89..f72ec0b7b7 100644 --- a/src/pocketmine/block/Sponge.php +++ b/src/pocketmine/block/Sponge.php @@ -37,6 +37,10 @@ class Sponge extends Solid{ $this->wet = $stateMeta !== 0; } + public function getStateBitmask() : int{ + return 0b1; + } + public function getHardness() : float{ return 0.6; } diff --git a/src/pocketmine/block/Stair.php b/src/pocketmine/block/Stair.php index df2af2a3ff..a66ef1d11d 100644 --- a/src/pocketmine/block/Stair.php +++ b/src/pocketmine/block/Stair.php @@ -53,6 +53,10 @@ abstract class Stair extends Transparent{ $this->upsideDown = ($stateMeta & 0x04) !== 0; } + public function getStateBitmask() : int{ + return 0b111; + } + public function readStateFromWorld() : void{ parent::readStateFromWorld(); diff --git a/src/pocketmine/block/StandingBanner.php b/src/pocketmine/block/StandingBanner.php index 53603b471c..e20490fbb8 100644 --- a/src/pocketmine/block/StandingBanner.php +++ b/src/pocketmine/block/StandingBanner.php @@ -46,6 +46,10 @@ class StandingBanner extends Transparent{ $this->rotation = $stateMeta; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function getHardness() : float{ return 1; } diff --git a/src/pocketmine/block/Sugarcane.php b/src/pocketmine/block/Sugarcane.php index 2bf55b58bb..6a02812130 100644 --- a/src/pocketmine/block/Sugarcane.php +++ b/src/pocketmine/block/Sugarcane.php @@ -44,6 +44,10 @@ 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){ diff --git a/src/pocketmine/block/Torch.php b/src/pocketmine/block/Torch.php index bd97b94b90..7e076f7c57 100644 --- a/src/pocketmine/block/Torch.php +++ b/src/pocketmine/block/Torch.php @@ -39,10 +39,13 @@ 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; } diff --git a/src/pocketmine/block/Trapdoor.php b/src/pocketmine/block/Trapdoor.php index d3cacbd899..1cc736894d 100644 --- a/src/pocketmine/block/Trapdoor.php +++ b/src/pocketmine/block/Trapdoor.php @@ -54,6 +54,10 @@ class Trapdoor extends Transparent{ $this->open = ($stateMeta & self::MASK_OPENED) !== 0; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function getHardness() : float{ return 3; } diff --git a/src/pocketmine/block/Tripwire.php b/src/pocketmine/block/Tripwire.php index e82c15d522..3b68142ac4 100644 --- a/src/pocketmine/block/Tripwire.php +++ b/src/pocketmine/block/Tripwire.php @@ -45,6 +45,10 @@ class Tripwire extends Flowable{ $this->disarmed = ($stateMeta & 0x08) !== 0; } + public function getStateBitmask() : int{ + return 0b1111; + } + public function isAffectedBySilkTouch() : bool{ return false; } diff --git a/src/pocketmine/block/TripwireHook.php b/src/pocketmine/block/TripwireHook.php index 7f9770530b..b91887f36b 100644 --- a/src/pocketmine/block/TripwireHook.php +++ b/src/pocketmine/block/TripwireHook.php @@ -49,6 +49,10 @@ 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 diff --git a/src/pocketmine/block/Vine.php b/src/pocketmine/block/Vine.php index 44a6b206ac..27b59636a9 100644 --- a/src/pocketmine/block/Vine.php +++ b/src/pocketmine/block/Vine.php @@ -57,6 +57,10 @@ 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; diff --git a/src/pocketmine/block/WallBanner.php b/src/pocketmine/block/WallBanner.php index ede176c85d..7acdba5b78 100644 --- a/src/pocketmine/block/WallBanner.php +++ b/src/pocketmine/block/WallBanner.php @@ -39,6 +39,10 @@ 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); diff --git a/src/pocketmine/block/WallSign.php b/src/pocketmine/block/WallSign.php index cf2c615aa4..79f85999af 100644 --- a/src/pocketmine/block/WallSign.php +++ b/src/pocketmine/block/WallSign.php @@ -39,6 +39,10 @@ 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); diff --git a/src/pocketmine/block/WeightedPressurePlate.php b/src/pocketmine/block/WeightedPressurePlate.php index 7c3d310c15..fb3c00051b 100644 --- a/src/pocketmine/block/WeightedPressurePlate.php +++ b/src/pocketmine/block/WeightedPressurePlate.php @@ -37,4 +37,8 @@ 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; + } } diff --git a/src/pocketmine/block/utils/PillarRotationTrait.php b/src/pocketmine/block/utils/PillarRotationTrait.php index 5ddc5fc12a..7113ae764e 100644 --- a/src/pocketmine/block/utils/PillarRotationTrait.php +++ b/src/pocketmine/block/utils/PillarRotationTrait.php @@ -52,6 +52,14 @@ 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,