From 56d9943b0d10832c6416b3a5983ec7038fb0efd2 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 21 Sep 2018 19:28:10 +0100 Subject: [PATCH] Nuke Block->meta, split into variant and state properties, lots of cleanup This is a major change to the way block metadata is handled within the PM core. This separates variant metadata (which really ought to be part of the ID) from state metadata, and in a couple of cases flattens separate states of blocks together. The result of this is that invalid variants can be much more easily detected, and additionally state handling is much cleaner since meta is only needed at the serialize layer instead of throughout the code. --- src/pocketmine/Player.php | 1 + src/pocketmine/block/Air.php | 4 +- src/pocketmine/block/Anvil.php | 36 +-- src/pocketmine/block/BaseRail.php | 59 ++-- src/pocketmine/block/Bed.php | 74 +++-- src/pocketmine/block/Bedrock.php | 4 +- src/pocketmine/block/Beetroot.php | 6 +- src/pocketmine/block/Block.php | 53 ++-- src/pocketmine/block/BlockFactory.php | 296 ++++++++++++++---- src/pocketmine/block/BoneBlock.php | 14 +- src/pocketmine/block/Bookshelf.php | 4 +- src/pocketmine/block/BrewingStand.php | 29 +- src/pocketmine/block/BrickStairs.php | 4 +- src/pocketmine/block/Bricks.php | 4 +- src/pocketmine/block/BurningFurnace.php | 96 ------ src/pocketmine/block/Button.php | 26 +- src/pocketmine/block/Cactus.php | 29 +- src/pocketmine/block/Cake.php | 25 +- src/pocketmine/block/Carpet.php | 11 - src/pocketmine/block/Carrot.php | 6 +- src/pocketmine/block/Chest.php | 27 +- src/pocketmine/block/Clay.php | 4 +- src/pocketmine/block/Coal.php | 4 +- src/pocketmine/block/CoalOre.php | 4 +- src/pocketmine/block/Cobblestone.php | 4 +- src/pocketmine/block/CobblestoneStairs.php | 4 +- src/pocketmine/block/CobblestoneWall.php | 14 - src/pocketmine/block/Cobweb.php | 4 +- src/pocketmine/block/CocoaBlock.php | 30 +- src/pocketmine/block/Concrete.php | 11 - src/pocketmine/block/ConcretePowder.php | 13 +- src/pocketmine/block/CraftingTable.php | 4 +- src/pocketmine/block/Crops.php | 28 +- src/pocketmine/block/Dandelion.php | 4 +- src/pocketmine/block/DaylightSensor.php | 36 ++- src/pocketmine/block/DeadBush.php | 4 +- src/pocketmine/block/Diamond.php | 4 +- src/pocketmine/block/DiamondOre.php | 4 +- src/pocketmine/block/Dirt.php | 17 +- src/pocketmine/block/Door.php | 166 +++++----- src/pocketmine/block/DoublePlant.php | 60 ++-- src/pocketmine/block/DoubleSlab.php | 37 ++- src/pocketmine/block/DoubleStoneSlab.php | 47 --- src/pocketmine/block/DoubleStoneSlab2.php | 33 -- src/pocketmine/block/DoubleWoodenSlab.php | 49 --- src/pocketmine/block/Emerald.php | 4 +- src/pocketmine/block/EmeraldOre.php | 4 +- src/pocketmine/block/EnchantingTable.php | 4 +- src/pocketmine/block/EndPortalFrame.php | 36 ++- src/pocketmine/block/EndRod.php | 42 ++- src/pocketmine/block/EndStone.php | 4 +- src/pocketmine/block/EndStoneBricks.php | 4 +- src/pocketmine/block/EnderChest.php | 4 +- src/pocketmine/block/Farmland.php | 27 +- src/pocketmine/block/Fence.php | 4 - src/pocketmine/block/FenceGate.php | 40 ++- src/pocketmine/block/Fire.php | 33 +- src/pocketmine/block/Flower.php | 21 -- src/pocketmine/block/FlowerPot.php | 28 +- src/pocketmine/block/Furnace.php | 88 +++++- src/pocketmine/block/Glass.php | 10 - src/pocketmine/block/GlassPane.php | 10 - src/pocketmine/block/GlazedTerracotta.php | 22 +- src/pocketmine/block/GlowingObsidian.php | 4 +- src/pocketmine/block/GlowingRedstoneOre.php | 58 ---- src/pocketmine/block/Glowstone.php | 4 +- src/pocketmine/block/Gold.php | 4 +- src/pocketmine/block/GoldOre.php | 4 +- src/pocketmine/block/Grass.php | 4 +- src/pocketmine/block/GrassPath.php | 4 +- src/pocketmine/block/Gravel.php | 4 +- src/pocketmine/block/HardenedClay.php | 10 - src/pocketmine/block/HayBale.php | 14 +- src/pocketmine/block/Ice.php | 4 +- src/pocketmine/block/Iron.php | 4 +- src/pocketmine/block/IronBars.php | 8 +- src/pocketmine/block/IronDoor.php | 4 +- src/pocketmine/block/IronOre.php | 4 +- src/pocketmine/block/ItemFrame.php | 27 +- src/pocketmine/block/Ladder.php | 35 ++- src/pocketmine/block/Lapis.php | 4 +- src/pocketmine/block/LapisOre.php | 4 +- src/pocketmine/block/Lava.php | 16 +- src/pocketmine/block/Leaves.php | 70 ++--- src/pocketmine/block/Leaves2.php | 48 --- src/pocketmine/block/Lever.php | 92 ++++-- src/pocketmine/block/Liquid.php | 163 +++++----- src/pocketmine/block/LitRedstoneLamp.php | 37 --- src/pocketmine/block/Magma.php | 4 +- src/pocketmine/block/Melon.php | 4 +- src/pocketmine/block/MelonStem.php | 8 +- src/pocketmine/block/MonsterSpawner.php | 4 +- src/pocketmine/block/Mycelium.php | 4 +- src/pocketmine/block/NetherBrickFence.php | 4 + src/pocketmine/block/NetherBrickStairs.php | 4 +- src/pocketmine/block/NetherQuartzOre.php | 4 +- src/pocketmine/block/NetherReactor.php | 30 +- src/pocketmine/block/NetherWartBlock.php | 4 +- src/pocketmine/block/NetherWartPlant.php | 25 +- src/pocketmine/block/Netherrack.php | 4 +- src/pocketmine/block/NoteBlock.php | 4 +- src/pocketmine/block/Obsidian.php | 4 +- src/pocketmine/block/PackedIce.php | 4 +- src/pocketmine/block/Planks.php | 24 -- src/pocketmine/block/Podzol.php | 4 +- src/pocketmine/block/Potato.php | 6 +- src/pocketmine/block/Prismarine.php | 19 -- src/pocketmine/block/Pumpkin.php | 8 +- src/pocketmine/block/PumpkinStem.php | 8 +- src/pocketmine/block/Purpur.php | 12 - src/pocketmine/block/PurpurStairs.php | 4 +- src/pocketmine/block/Quartz.php | 27 +- src/pocketmine/block/QuartzStairs.php | 4 +- src/pocketmine/block/Rail.php | 4 +- src/pocketmine/block/RedMushroom.php | 4 +- src/pocketmine/block/RedMushroomBlock.php | 25 +- src/pocketmine/block/RedSandstone.php | 37 --- src/pocketmine/block/Redstone.php | 4 +- src/pocketmine/block/RedstoneLamp.php | 25 +- src/pocketmine/block/RedstoneOre.php | 48 ++- src/pocketmine/block/RedstoneRail.php | 20 +- src/pocketmine/block/RedstoneTorch.php | 19 +- src/pocketmine/block/RedstoneTorchUnlit.php | 37 --- src/pocketmine/block/Sand.php | 14 - src/pocketmine/block/Sandstone.php | 19 -- src/pocketmine/block/SandstoneStairs.php | 4 +- src/pocketmine/block/Sapling.php | 37 +-- src/pocketmine/block/SeaLantern.php | 4 +- src/pocketmine/block/SignPost.php | 29 +- src/pocketmine/block/Skull.php | 23 +- src/pocketmine/block/Slab.php | 66 ++-- src/pocketmine/block/Snow.php | 4 +- src/pocketmine/block/SnowLayer.php | 19 +- src/pocketmine/block/SoulSand.php | 4 +- src/pocketmine/block/Sponge.php | 19 +- src/pocketmine/block/StainedClay.php | 35 --- src/pocketmine/block/StainedGlass.php | 35 --- src/pocketmine/block/StainedGlassPane.php | 35 --- src/pocketmine/block/Stair.php | 49 +-- src/pocketmine/block/StandingBanner.php | 28 +- src/pocketmine/block/Stone.php | 23 +- src/pocketmine/block/StoneBrickStairs.php | 4 +- src/pocketmine/block/StoneBricks.php | 16 - src/pocketmine/block/StonePressurePlate.php | 23 +- src/pocketmine/block/StoneSlab.php | 28 -- src/pocketmine/block/StoneSlab2.php | 44 --- src/pocketmine/block/Stonecutter.php | 4 +- src/pocketmine/block/Sugarcane.php | 31 +- src/pocketmine/block/TNT.php | 4 +- src/pocketmine/block/TallGrass.php | 15 - src/pocketmine/block/Torch.php | 34 +- src/pocketmine/block/Trapdoor.php | 56 ++-- src/pocketmine/block/Tripwire.php | 25 +- src/pocketmine/block/TripwireHook.php | 40 ++- src/pocketmine/block/UnknownBlock.php | 9 + src/pocketmine/block/Vine.php | 85 ++--- src/pocketmine/block/WallBanner.php | 19 +- src/pocketmine/block/WallSign.php | 19 +- src/pocketmine/block/Water.php | 8 +- src/pocketmine/block/WaterLily.php | 8 +- .../block/WeightedPressurePlateLight.php | 23 +- src/pocketmine/block/Wheat.php | 6 +- src/pocketmine/block/Wood.php | 27 +- src/pocketmine/block/Wood2.php | 41 --- src/pocketmine/block/WoodenFence.php | 20 -- src/pocketmine/block/WoodenSlab.php | 18 +- src/pocketmine/block/Wool.php | 11 - .../block/utils/ColorBlockMetaHelper.php | 50 --- .../block/utils/PillarRotationHelper.php | 39 --- src/pocketmine/item/Bucket.php | 2 +- src/pocketmine/item/Dye.php | 10 + src/pocketmine/level/Level.php | 51 +-- src/pocketmine/level/biome/ForestBiome.php | 4 +- src/pocketmine/level/biome/TaigaBiome.php | 4 +- .../level/generator/object/Tree.php | 14 +- .../level/generator/populator/Tree.php | 4 +- src/pocketmine/tile/Furnace.php | 15 +- tests/phpunit/block/BlockTest.php | 16 +- 178 files changed, 2012 insertions(+), 2120 deletions(-) delete mode 100644 src/pocketmine/block/BurningFurnace.php delete mode 100644 src/pocketmine/block/DoubleStoneSlab.php delete mode 100644 src/pocketmine/block/DoubleStoneSlab2.php delete mode 100644 src/pocketmine/block/DoubleWoodenSlab.php delete mode 100644 src/pocketmine/block/GlowingRedstoneOre.php delete mode 100644 src/pocketmine/block/Leaves2.php delete mode 100644 src/pocketmine/block/LitRedstoneLamp.php delete mode 100644 src/pocketmine/block/RedSandstone.php delete mode 100644 src/pocketmine/block/RedstoneTorchUnlit.php delete mode 100644 src/pocketmine/block/StainedClay.php delete mode 100644 src/pocketmine/block/StainedGlass.php delete mode 100644 src/pocketmine/block/StainedGlassPane.php delete mode 100644 src/pocketmine/block/StoneSlab2.php delete mode 100644 src/pocketmine/block/Wood2.php delete mode 100644 src/pocketmine/block/utils/ColorBlockMetaHelper.php delete mode 100644 src/pocketmine/block/utils/PillarRotationHelper.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 471523998..1489fd781 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2448,6 +2448,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ public function handleItemFrameDropItem(ItemFrameDropItemPacket $packet) : bool{ $tile = $this->level->getTileAt($packet->x, $packet->y, $packet->z); if($tile instanceof ItemFrame){ + //TODO: use facing blockstate property instead of damage value $ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $tile->getBlock(), null, 5 - $tile->getBlock()->getDamage(), PlayerInteractEvent::LEFT_CLICK_BLOCK); if($this->isSpectator() or $this->level->checkSpawnProtection($this, $tile)){ $ev->setCancelled(); diff --git a/src/pocketmine/block/Air.php b/src/pocketmine/block/Air.php index 9984e3fe2..8451e5a19 100644 --- a/src/pocketmine/block/Air.php +++ b/src/pocketmine/block/Air.php @@ -34,8 +34,8 @@ class Air extends Transparent{ protected $id = self::AIR; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Anvil.php b/src/pocketmine/block/Anvil.php index aa468082c..d3212e03b 100644 --- a/src/pocketmine/block/Anvil.php +++ b/src/pocketmine/block/Anvil.php @@ -28,6 +28,7 @@ use pocketmine\item\Item; use pocketmine\item\TieredTool; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Bearing; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; @@ -37,10 +38,19 @@ class Anvil extends Fallable{ public const TYPE_SLIGHTLY_DAMAGED = 4; public const TYPE_VERY_DAMAGED = 8; - protected $id = self::ANVIL; + /** @var int */ + protected $facing = Facing::NORTH; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + protected function writeStateToMeta() : int{ + return Bearing::fromFacing($this->facing); + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = Bearing::toFacing($meta); + } + + public function getStateBitmask() : int{ + return 0b11; } public function isTransparent() : bool{ @@ -55,19 +65,6 @@ class Anvil extends Fallable{ return 6000; } - public function getVariantBitmask() : int{ - return 0x0c; - } - - public function getName() : string{ - static $names = [ - self::TYPE_NORMAL => "Anvil", - self::TYPE_SLIGHTLY_DAMAGED => "Slightly Damaged Anvil", - self::TYPE_VERY_DAMAGED => "Very Damaged Anvil" - ]; - return $names[$this->getVariant()] ?? "Anvil"; - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } @@ -79,7 +76,7 @@ class Anvil extends Fallable{ public function recalculateBoundingBox() : ?AxisAlignedBB{ $inset = 0.125; - if($this->meta & 0x01){ //east/west + if(Facing::axis($this->facing) === Facing::AXIS_X){ return new AxisAlignedBB(0, 0, $inset, 1, 1, 1 - $inset); }else{ return new AxisAlignedBB($inset, 0, 0, 1 - $inset, 1, 1); @@ -95,8 +92,9 @@ class Anvil extends Fallable{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - $direction = $player !== null ? Bearing::rotate($player->getDirection(), 1) : 0; - $this->meta = $this->getVariant() | $direction; + if($player !== null){ + $this->facing = Bearing::toFacing(Bearing::rotate($player->getDirection(), 1)); + } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } } diff --git a/src/pocketmine/block/BaseRail.php b/src/pocketmine/block/BaseRail.php index d7a2096b9..b7a0d96b6 100644 --- a/src/pocketmine/block/BaseRail.php +++ b/src/pocketmine/block/BaseRail.php @@ -37,13 +37,6 @@ abstract class BaseRail extends Flowable{ public const ASCENDING_NORTH = 4; public const ASCENDING_SOUTH = 5; - private const ASCENDING_SIDES = [ - self::ASCENDING_NORTH => Facing::NORTH, - self::ASCENDING_EAST => Facing::EAST, - self::ASCENDING_SOUTH => Facing::SOUTH, - self::ASCENDING_WEST => Facing::WEST - ]; - protected const FLAG_ASCEND = 1 << 24; //used to indicate direction-up protected const CONNECTIONS = [ @@ -76,8 +69,28 @@ abstract class BaseRail extends Flowable{ ] ]; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int[] */ + protected $connections = []; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + if(empty($this->connections)){ + return self::STRAIGHT_NORTH_SOUTH; + } + return $this->getMetaForState($this->connections); + } + + public function readStateFromMeta(int $meta) : void{ + //on invalid states, this will return an empty array, allowing this rail to transform into any other state + //TODO: should this throw instead? + $this->connections = $this->getConnectionsFromMeta($meta); + } + + public function getStateBitmask() : int{ + return 0b111; } public function getHardness() : float{ @@ -121,9 +134,11 @@ abstract class BaseRail extends Flowable{ /** * Returns the connection directions of this rail (depending on the current block state) * + * @param int $meta + * * @return int[] */ - abstract protected function getConnectionsForState() : array; + abstract protected function getConnectionsFromMeta(int $meta) : array; /** * Returns all the directions this rail is already connected in. @@ -135,7 +150,7 @@ abstract class BaseRail extends Flowable{ $connections = []; /** @var int $connection */ - foreach($this->getConnectionsForState() as $connection){ + foreach($this->connections as $connection){ $other = $this->getSide($connection & ~self::FLAG_ASCEND); $otherConnection = Facing::opposite($connection & ~self::FLAG_ASCEND); @@ -149,7 +164,7 @@ abstract class BaseRail extends Flowable{ if( $other instanceof BaseRail and - in_array($otherConnection, $other->getConnectionsForState(), true) + in_array($otherConnection, $other->connections, true) ){ $connections[] = $connection; } @@ -248,20 +263,20 @@ abstract class BaseRail extends Flowable{ throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections)); } - $this->meta = $this->getMetaForState($connections); + $this->connections = $connections; $this->level->setBlock($this, $this, false, false); //avoid recursion } public function onNearbyBlockChange() : void{ - if($this->getSide(Facing::DOWN)->isTransparent() or ( - isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and - $this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent() - )){ - $this->getLevel()->useBreakOn($this); + if($this->getSide(Facing::DOWN)->isTransparent()){ + $this->level->useBreakOn($this); + }else{ + foreach($this->connections as $connection){ + if(($connection & self::FLAG_ASCEND) !== 0 and $this->getSide($connection & ~self::FLAG_ASCEND)->isTransparent()){ + $this->level->useBreakOn($this); + break; + } + } } } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/Bed.php b/src/pocketmine/block/Bed.php index d0dfb28fd..0e98356f1 100644 --- a/src/pocketmine/block/Bed.php +++ b/src/pocketmine/block/Bed.php @@ -37,15 +37,38 @@ use pocketmine\tile\Tile; use pocketmine\utils\TextFormat; class Bed extends Transparent{ - public const BITFLAG_OCCUPIED = 0x04; - public const BITFLAG_HEAD = 0x08; + private const BITFLAG_OCCUPIED = 0x04; + private const BITFLAG_HEAD = 0x08; protected $id = self::BED_BLOCK; protected $itemId = Item::BED; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $occupied = false; + /** @var bool */ + protected $head = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return Bearing::fromFacing($this->facing) | + ($this->occupied ? self::BITFLAG_OCCUPIED : 0) | + ($this->head ? self::BITFLAG_HEAD : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = Bearing::toFacing($meta & 0x03); + $this->occupied = ($meta & self::BITFLAG_OCCUPIED) !== 0; + $this->head = ($meta & self::BITFLAG_HEAD) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getHardness() : float{ @@ -61,51 +84,39 @@ class Bed extends Transparent{ } public function isHeadPart() : bool{ - return ($this->meta & self::BITFLAG_HEAD) !== 0; + return $this->head; } /** * @return bool */ public function isOccupied() : bool{ - return ($this->meta & self::BITFLAG_OCCUPIED) !== 0; + return $this->occupied; } public function setOccupied(bool $occupied = true){ - if($occupied){ - $this->meta |= self::BITFLAG_OCCUPIED; - }else{ - $this->meta &= ~self::BITFLAG_OCCUPIED; - } + $this->occupied = $occupied; + $this->level->setBlock($this, $this, false, false); - $this->getLevel()->setBlock($this, $this, false, false); - - if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){ - $other->setOccupied($occupied); + if(($other = $this->getOtherHalf()) !== null){ + $other->occupied = $occupied; + $this->level->setBlock($other, $other, false, false); } } /** - * @param int $meta - * @param bool $isHead - * * @return int */ - public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{ - $side = Bearing::toFacing($meta & 0x03); - if($isHead){ - $side = Facing::opposite($side); - } - - return $side; + private function getOtherHalfSide() : int{ + return $this->head ? Facing::opposite($this->facing) : $this->facing; } /** * @return Bed|null */ public function getOtherHalf() : ?Bed{ - $other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart())); - if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){ + $other = $this->getSide($this->getOtherHalfSide()); + if($other instanceof Bed and $other->head !== $this->head and $other->facing === $this->facing){ return $other; } @@ -152,11 +163,14 @@ class Bed extends Transparent{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ $down = $this->getSide(Facing::DOWN); if(!$down->isTransparent()){ - $this->meta = $player instanceof Player ? $player->getDirection() : 0; - $next = $this->getSide(self::getOtherHalfSide($this->meta)); + $this->facing = $player !== null ? Bearing::toFacing($player->getDirection()) : Facing::NORTH; + + $next = $this->getSide($this->getOtherHalfSide()); if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){ parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); - $this->getLevel()->setBlock($next, BlockFactory::get($this->id, $this->meta | self::BITFLAG_HEAD), true, true); + $nextState = clone $this; + $nextState->head = true; + $this->getLevel()->setBlock($next, $nextState, true, true); Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player)); diff --git a/src/pocketmine/block/Bedrock.php b/src/pocketmine/block/Bedrock.php index 403fc495d..c17173855 100644 --- a/src/pocketmine/block/Bedrock.php +++ b/src/pocketmine/block/Bedrock.php @@ -29,8 +29,8 @@ class Bedrock extends Solid{ protected $id = self::BEDROCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Beetroot.php b/src/pocketmine/block/Beetroot.php index 783fe6e09..c63d3f86f 100644 --- a/src/pocketmine/block/Beetroot.php +++ b/src/pocketmine/block/Beetroot.php @@ -30,16 +30,12 @@ class Beetroot extends Crops{ protected $id = self::BEETROOT_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getName() : string{ return "Beetroot Block"; } public function getDropsForCompatibleTool(Item $item) : array{ - if($this->meta >= 0x07){ + if($this->age >= 7){ return [ ItemFactory::get(Item::BEETROOT), ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3)) diff --git a/src/pocketmine/block/Block.php b/src/pocketmine/block/Block.php index 20d195dfa..bdb8871d7 100644 --- a/src/pocketmine/block/Block.php +++ b/src/pocketmine/block/Block.php @@ -60,7 +60,7 @@ class Block extends Position implements BlockIds, Metadatable{ /** @var int */ protected $id; /** @var int */ - protected $meta = 0; + protected $variant = 0; /** @var string|null */ protected $fallbackName; /** @var int|null */ @@ -74,14 +74,18 @@ class Block extends Position implements BlockIds, Metadatable{ protected $collisionBoxes = null; /** - * @param int $id The block type's ID, 0-255 - * @param int $meta Meta value of the block type - * @param string|null $name English name of the block type (TODO: implement translations) - * @param int $itemId The item ID of the block type, used for block picking and dropping items. + * @param int $id The block type's ID, 0-255 + * @param int $variant Meta value of the block type + * @param string|null $name English name of the block type (TODO: implement translations) + * @param int $itemId The item ID of the block type, used for block picking and dropping items. */ - public function __construct(int $id, int $meta = 0, string $name = null, int $itemId = null){ + public function __construct(int $id, int $variant = 0, string $name = null, int $itemId = null){ $this->id = $id; - $this->meta = $meta; + + if(($variant & $this->getStateBitmask()) !== 0){ + throw new \InvalidArgumentException("Variant 0x" . dechex($variant) . " collides with state bitmask 0x" . dechex($this->getStateBitmask())); + } + $this->variant = $variant; $this->fallbackName = $name; $this->itemId = $itemId; } @@ -122,30 +126,26 @@ class Block extends Position implements BlockIds, Metadatable{ * @return int */ public function getDamage() : int{ - return $this->meta; + $stateMeta = $this->writeStateToMeta(); + assert(($stateMeta & ~$this->getStateBitmask()) === 0); + return $this->variant | $stateMeta; + } + + protected function writeStateToMeta() : int{ + return 0; + } + + public function readStateFromMeta(int $meta) : void{ + //NOOP } /** - * @param int $meta - */ - public function setDamage(int $meta) : void{ - if($meta < 0 or $meta > 0xf){ - throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta"); - } - $this->meta = $meta; - } - - /** - * Bitmask to use to remove superfluous information from block meta when getting its item form or name. - * This defaults to -1 (don't remove any data). Used to remove rotation data and bitflags from block drops. - * - * If your block should not have any meta value when it's dropped as an item, override this to return 0 in - * descendent classes. + * Returns a bitmask used to extract state bits from block metadata. * * @return int */ - public function getVariantBitmask() : int{ - return -1; + public function getStateBitmask() : int{ + return 0; } /** @@ -153,10 +153,9 @@ class Block extends Position implements BlockIds, Metadatable{ * @return int */ public function getVariant() : int{ - return $this->meta & $this->getVariantBitmask(); + return $this->variant; } - /** * AKA: Block->isPlaceable * @return bool diff --git a/src/pocketmine/block/BlockFactory.php b/src/pocketmine/block/BlockFactory.php index 6089234ac..f8a091ce7 100644 --- a/src/pocketmine/block/BlockFactory.php +++ b/src/pocketmine/block/BlockFactory.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\block\utils\Color; +use pocketmine\block\utils\WoodType; use pocketmine\item\Item; use pocketmine\level\Position; @@ -32,6 +34,8 @@ use pocketmine\level\Position; class BlockFactory{ /** @var \SplFixedArray */ private static $fullList = null; + /** @var \SplFixedArray|\Closure[] */ + private static $getInterceptors = null; /** @var \SplFixedArray */ public static $lightFilter = null; @@ -40,6 +44,9 @@ class BlockFactory{ /** @var \SplFixedArray */ public static $blastResistance = null; + /** @var \SplFixedArray|int[] */ + public static $stateMasks = null; + /** @var int[] */ public static $staticRuntimeIdMap = []; @@ -55,56 +62,138 @@ class BlockFactory{ */ public static function init() : void{ self::$fullList = new \SplFixedArray(4096); + self::$getInterceptors = new \SplFixedArray(4096); self::$lightFilter = \SplFixedArray::fromArray(array_fill(0, 256, 1)); self::$diffusesSkyLight = \SplFixedArray::fromArray(array_fill(0, 256, false)); self::$blastResistance = \SplFixedArray::fromArray(array_fill(0, 256, 0)); + self::$stateMasks = \SplFixedArray::fromArray(array_fill(0, 256, 0)); + self::registerBlock(new Air()); - self::registerBlock(new Stone()); + + //TODO: give smooth stone its own class (different drops) + self::registerBlock(new Stone(Block::STONE, Stone::NORMAL, "Stone")); + self::registerBlock(new Stone(Block::STONE, Stone::GRANITE, "Granite")); + self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_GRANITE, "Polished Granite")); + self::registerBlock(new Stone(Block::STONE, Stone::DIORITE, "Diorite")); + self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_DIORITE, "Polished Diorite")); + self::registerBlock(new Stone(Block::STONE, Stone::ANDESITE, "Andesite")); + self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_ANDESITE, "Polished Andesite")); + self::registerBlock(new Grass()); - self::registerBlock(new Dirt()); + + //TODO: split these into separate classes + self::registerBlock(new Dirt(Block::DIRT, Dirt::NORMAL, "Dirt")); + self::registerBlock(new Dirt(Block::DIRT, Dirt::COARSE, "Coarse Dirt")); + self::registerBlock(new Cobblestone()); - self::registerBlock(new Planks()); - self::registerBlock(new Sapling()); + + foreach(WoodType::ALL as $type){ + self::registerBlock(new Planks(Block::PLANKS, $type, WoodType::NAMES[$type] . " Planks")); + self::registerBlock(new Sapling(Block::SAPLING, $type, WoodType::NAMES[$type] . " Sapling")); + self::registerBlock(new WoodenFence(Block::FENCE, $type, WoodType::NAMES[$type] . " Fence")); + } + + foreach(WoodType::ALL as $type){ + //TODO: find a better way to deal with this split + self::registerBlock(new Wood($type >= 4 ? Block::WOOD2 : Block::WOOD, $type & 0x03, WoodType::NAMES[$type] . " Wood")); + self::registerBlock(new Leaves($type >= 4 ? Block::LEAVES2 : Block::LEAVES, $type & 0x03, $type, WoodType::NAMES[$type] . " Leaves")); + } + self::registerBlock(new Bedrock()); self::registerBlock(new Water()); self::registerBlock(new StillWater()); self::registerBlock(new Lava()); self::registerBlock(new StillLava()); - self::registerBlock(new Sand()); + + self::registerBlock(new Sand(Block::SAND, 0, "Sand")); + self::registerBlock(new Sand(Block::SAND, 1, "Red Sand")); + self::registerBlock(new Gravel()); self::registerBlock(new GoldOre()); self::registerBlock(new IronOre()); self::registerBlock(new CoalOre()); - self::registerBlock(new Wood()); - self::registerBlock(new Leaves()); self::registerBlock(new Sponge()); - self::registerBlock(new Glass()); + self::registerBlock(new Glass(Block::GLASS, 0, "Glass")); self::registerBlock(new LapisOre()); self::registerBlock(new Lapis()); //TODO: DISPENSER - self::registerBlock(new Sandstone()); + + static $sandstoneTypes = [ + Sandstone::NORMAL => "", + Sandstone::CHISELED => "Chiseled ", + Sandstone::SMOOTH => "Smooth " + ]; + foreach($sandstoneTypes as $variant => $prefix){ + self::registerBlock(new Sandstone(Block::SANDSTONE, $variant, $prefix . "Sandstone")); + self::registerBlock(new Sandstone(Block::RED_SANDSTONE, $variant, $prefix . "Red Sandstone")); + } + self::registerBlock(new NoteBlock()); self::registerBlock(new Bed()); self::registerBlock(new PoweredRail()); self::registerBlock(new DetectorRail()); //TODO: STICKY_PISTON self::registerBlock(new Cobweb()); - self::registerBlock(new TallGrass()); + + self::registerBlock(new TallGrass(Block::TALL_GRASS, 0, "Fern")); + self::registerBlock(new TallGrass(Block::TALL_GRASS, 1, "Tall Grass")); + self::registerBlock(new TallGrass(Block::TALL_GRASS, 2, "Fern")); + self::registerBlock(new TallGrass(Block::TALL_GRASS, 3, "Fern")); + self::registerBlock(new DeadBush()); //TODO: PISTON //TODO: PISTONARMCOLLISION - self::registerBlock(new Wool()); + + foreach(Color::ALL as $color){ + self::registerBlock(new Wool(Block::WOOL, $color, Color::NAMES[$color] . " Wool")); + self::registerBlock(new HardenedClay(Block::STAINED_CLAY, $color, Color::NAMES[$color] . " Stained Clay")); + self::registerBlock(new Glass(Block::STAINED_GLASS, $color, Color::NAMES[$color] . " Stained Glass")); + self::registerBlock(new GlassPane(Block::STAINED_GLASS_PANE, $color, Color::NAMES[$color] . " Stained Glass Pane")); + self::registerBlock(new Carpet(Block::CARPET, $color, Color::NAMES[$color] . " Carpet")); + self::registerBlock(new Concrete(Block::CONCRETE, $color, Color::NAMES[$color] . " Concrete")); + self::registerBlock(new ConcretePowder(Block::CONCRETE_POWDER, $color, Color::NAMES[$color] . " Concrete Powder")); + } self::registerBlock(new Dandelion()); - self::registerBlock(new Flower()); + + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_POPPY, "Poppy")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_BLUE_ORCHID, "Blue Orchid")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_ALLIUM, "Allium")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_AZURE_BLUET, "Azure Bluet")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_RED_TULIP, "Red Tulip")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_ORANGE_TULIP, "Orange Tulip")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_WHITE_TULIP, "White Tulip")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_PINK_TULIP, "Pink Tulip")); + self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_OXEYE_DAISY, "Oxeye Daisy")); + self::registerBlock(new BrownMushroom()); self::registerBlock(new RedMushroom()); self::registerBlock(new Gold()); self::registerBlock(new Iron()); - self::registerBlock(new DoubleStoneSlab()); - self::registerBlock(new StoneSlab()); + + /** @var Slab[] $slabTypes */ + $slabTypes = [ + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 0, "Stone"), + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 1, "Sandstone"), + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 2, "Fake Wooden"), + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 3, "Cobblestone"), + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 4, "Brick"), + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 5, "Stone Brick"), + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 6, "Quartz"), + new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 7, "Nether Brick"), + new StoneSlab(Block::STONE_SLAB2, Block::DOUBLE_STONE_SLAB2, 0, "Red Sandstone"), + new StoneSlab(Block::STONE_SLAB2, Block::DOUBLE_STONE_SLAB2, 1, "Purpur") + ]; + foreach(WoodType::ALL as $woodType){ + $slabTypes[] = new WoodenSlab($woodType); + } + foreach($slabTypes as $type){ + self::registerBlock($type); + self::registerBlock(new DoubleSlab($type->getDoubleSlabId(), $type->getId(), $type->getVariant())); + } + self::registerBlock(new Bricks()); self::registerBlock(new TNT()); self::registerBlock(new Bookshelf()); @@ -121,8 +210,16 @@ class BlockFactory{ self::registerBlock(new CraftingTable()); self::registerBlock(new Wheat()); self::registerBlock(new Farmland()); + self::registerBlock(new Furnace()); - self::registerBlock(new BurningFurnace()); + self::addGetInterceptor(Block::BURNING_FURNACE, 0, function() : Block{ + $block = self::get(Block::FURNACE); + if($block instanceof Furnace){ + $block->setLit(); + } + return $block; + }); + self::registerBlock(new SignPost()); self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR)); self::registerBlock(new Ladder()); @@ -134,9 +231,23 @@ class BlockFactory{ self::registerBlock(new IronDoor()); self::registerBlock(new WoodenPressurePlate()); self::registerBlock(new RedstoneOre()); - self::registerBlock(new GlowingRedstoneOre()); - self::registerBlock(new RedstoneTorchUnlit()); + self::addGetInterceptor(Block::GLOWING_REDSTONE_ORE, 0, function() : Block{ + $block = self::get(Block::REDSTONE_ORE); + if($block instanceof RedstoneOre){ + $block->setLit(); + } + return $block; + }); + self::registerBlock(new RedstoneTorch()); + self::addGetInterceptor(Block::UNLIT_REDSTONE_TORCH, 0, function() : Block{ + $block = self::get(Block::REDSTONE_TORCH); + if($block instanceof RedstoneTorch){ + $block->setLit(false); //default state is lit + } + return $block; + }); + self::registerBlock(new StoneButton()); self::registerBlock(new SnowLayer()); self::registerBlock(new Ice()); @@ -145,7 +256,7 @@ class BlockFactory{ self::registerBlock(new Clay()); self::registerBlock(new Sugarcane()); //TODO: JUKEBOX - self::registerBlock(new WoodenFence()); + self::registerBlock(new Pumpkin()); self::registerBlock(new Netherrack()); self::registerBlock(new SoulSand()); @@ -158,11 +269,16 @@ class BlockFactory{ //TODO: INVISIBLEBEDROCK self::registerBlock(new Trapdoor()); //TODO: MONSTER_EGG - self::registerBlock(new StoneBricks()); + + self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::NORMAL, "Stone Bricks")); + self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::MOSSY, "Mossy Stone Bricks")); + self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::CRACKED, "Cracked Stone Bricks")); + self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::CHISELED, "Chiseled Stone Bricks")); + self::registerBlock(new BrownMushroomBlock()); self::registerBlock(new RedMushroomBlock()); self::registerBlock(new IronBars()); - self::registerBlock(new GlassPane()); + self::registerBlock(new GlassPane(Block::GLASS_PANE, 0, "Glass Pane")); self::registerBlock(new Melon()); self::registerBlock(new PumpkinStem()); self::registerBlock(new MelonStem()); @@ -184,7 +300,14 @@ class BlockFactory{ self::registerBlock(new EndStone()); //TODO: DRAGON_EGG self::registerBlock(new RedstoneLamp()); - self::registerBlock(new LitRedstoneLamp()); + self::addGetInterceptor(Block::LIT_REDSTONE_LAMP, 0, function() : Block{ + $block = self::get(Block::REDSTONE_LAMP); + if($block instanceof RedstoneLamp){ + $block->setLit(); + } + return $block; + }); + //TODO: DROPPER self::registerBlock(new ActivatorRail()); self::registerBlock(new CocoaBlock()); @@ -199,50 +322,76 @@ class BlockFactory{ self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs")); //TODO: COMMAND_BLOCK //TODO: BEACON - self::registerBlock(new CobblestoneWall()); + + self::registerBlock(new CobblestoneWall(Block::COBBLESTONE_WALL, CobblestoneWall::NONE_MOSSY_WALL, "Cobblestone Wall")); + self::registerBlock(new CobblestoneWall(Block::COBBLESTONE_WALL, CobblestoneWall::MOSSY_WALL, "Mossy Cobblestone Wall")); + self::registerBlock(new FlowerPot()); self::registerBlock(new Carrot()); self::registerBlock(new Potato()); self::registerBlock(new WoodenButton()); self::registerBlock(new Skull()); - self::registerBlock(new Anvil()); + + self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_NORMAL, "Anvil")); + self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_SLIGHTLY_DAMAGED, "Slightly Damaged Anvil")); + self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_VERY_DAMAGED, "Very Damaged Anvil")); + self::registerBlock(new TrappedChest()); self::registerBlock(new WeightedPressurePlateLight()); self::registerBlock(new WeightedPressurePlateHeavy()); //TODO: COMPARATOR_BLOCK //TODO: POWERED_COMPARATOR self::registerBlock(new DaylightSensor()); + self::addGetInterceptor(Block::DAYLIGHT_SENSOR_INVERTED, 0, function() : Block{ + $block = self::get(Block::DAYLIGHT_SENSOR); + if($block instanceof DaylightSensor){ + $block->setInverted(); + } + return $block; + }); + self::registerBlock(new Redstone()); self::registerBlock(new NetherQuartzOre()); //TODO: HOPPER_BLOCK - self::registerBlock(new Quartz()); + + self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::NORMAL, "Quartz Block")); + self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::CHISELED, "Chiseled Quartz Block")); + self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::PILLAR, "Quartz Pillar")); + + self::registerBlock(new Purpur(Block::PURPUR_BLOCK, Purpur::NORMAL, "Purpur Block")); + self::registerBlock(new Purpur(Block::PURPUR_BLOCK, Purpur::PILLAR, "Purpur Pillar")); + self::registerBlock(new QuartzStairs()); - self::registerBlock(new DoubleWoodenSlab()); - self::registerBlock(new WoodenSlab()); - self::registerBlock(new StainedClay()); - self::registerBlock(new StainedGlassPane()); - self::registerBlock(new Leaves2()); - self::registerBlock(new Wood2()); + self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs")); self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs")); //TODO: SLIME self::registerBlock(new IronTrapdoor()); - self::registerBlock(new Prismarine()); + + self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::NORMAL, "Prismarine")); + self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::DARK, "Dark Prismarine")); + self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::BRICKS, "Prismarine Bricks")); + self::registerBlock(new SeaLantern()); self::registerBlock(new HayBale()); - self::registerBlock(new Carpet()); - self::registerBlock(new HardenedClay()); + + self::registerBlock(new HardenedClay(Block::HARDENED_CLAY, 0, "Hardened Clay")); self::registerBlock(new Coal()); self::registerBlock(new PackedIce()); - self::registerBlock(new DoublePlant()); + + self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 0, "Sunflower")); + self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 1, "Lilac")); + //TODO: double tallgrass and large fern have different behaviour than the others, so they should get their own classes + self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 2, "Double Tallgrass")); + self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 3, "Large Fern")); + self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 4, "Rose Bush")); + self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 5, "Peony")); + self::registerBlock(new StandingBanner()); self::registerBlock(new WallBanner()); - //TODO: DAYLIGHT_DETECTOR_INVERTED - self::registerBlock(new RedSandstone()); + self::registerBlock(new RedSandstoneStairs()); - self::registerBlock(new DoubleStoneSlab2()); - self::registerBlock(new StoneSlab2()); self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate")); self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate")); self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate")); @@ -259,7 +408,6 @@ class BlockFactory{ self::registerBlock(new GrassPath()); self::registerBlock(new ItemFrame()); //TODO: CHORUS_FLOWER - self::registerBlock(new Purpur()); self::registerBlock(new PurpurStairs()); @@ -292,11 +440,8 @@ class BlockFactory{ self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta")); self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta")); self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta")); - self::registerBlock(new Concrete()); - self::registerBlock(new ConcretePowder()); //TODO: CHORUS_PLANT - self::registerBlock(new StainedGlass()); self::registerBlock(new Podzol()); self::registerBlock(new Beetroot()); @@ -327,20 +472,17 @@ class BlockFactory{ */ public static function registerBlock(Block $block, bool $override = false) : void{ $id = $block->getId(); + $variant = $block->getVariant(); - if(!$override and self::isRegistered($id)){ + if(!$override and self::isRegistered($id, $variant)){ throw new \RuntimeException("Trying to overwrite an already registered block"); } - for($meta = 0; $meta < 16; ++$meta){ - $variant = clone $block; - $variant->setDamage($meta); - self::$fullList[($id << 4) | $meta] = $variant; + self::$fullList[($id << 4) | $variant] = clone $block; + if($variant === 0){ + //TODO: allow these to differ for different variants + self::fillStaticArrays($id, $block); } - - self::$lightFilter[$id] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter - self::$diffusesSkyLight[$id] = $block->diffusesSkyLight(); - self::$blastResistance[$id] = $block->getBlastResistance(); } /** @@ -357,16 +499,34 @@ class BlockFactory{ throw new \InvalidArgumentException("Block meta value $meta is out of bounds"); } + if(self::$stateMasks[$id] === null){ + $variant = 0; + $state = $meta; + }else{ + $variant = $meta & ~self::$stateMasks[$id]; + $state = $meta & self::$stateMasks[$id]; + } + + $index = ($id << 4) | $variant; + + /** @var Block|null $block */ + $block = null; try{ - if(self::$fullList[($id << 4) | $meta] !== null){ - $block = clone self::$fullList[($id << 4) | $meta]; - }else{ - $block = new UnknownBlock($id, $meta); + if(self::$getInterceptors[$index] !== null){ + $block = (self::$getInterceptors[$index])(); + }elseif(self::$fullList[$index] !== null){ + $block = clone self::$fullList[$index]; } }catch(\RuntimeException $e){ throw new \InvalidArgumentException("Block ID $id is out of bounds"); } + if($block !== null){ + $block->readStateFromMeta($state); + }else{ + $block = new UnknownBlock($id, $meta); + } + if($pos !== null){ $block->x = $pos->getFloorX(); $block->y = $pos->getFloorY(); @@ -377,22 +537,32 @@ class BlockFactory{ return $block; } - /** - * @internal - * @return \SplFixedArray - */ - public static function getBlockStatesArray() : \SplFixedArray{ - return self::$fullList; + public static function addGetInterceptor(int $id, int $variant, \Closure $interceptor) : void{ + $block = $interceptor(); + if(!($block instanceof Block)){ + throw new \InvalidArgumentException("Interceptor must return an instance of " . Block::class); + } + self::$getInterceptors[($id << 4) | $variant] = $interceptor; + self::fillStaticArrays($id, $block); + } + + private static function fillStaticArrays(int $id, Block $block) : void{ + self::$lightFilter[$id] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter + self::$diffusesSkyLight[$id] = $block->diffusesSkyLight(); + self::$blastResistance[$id] = $block->getBlastResistance(); + self::$stateMasks[$id] = $block->getStateBitmask(); } /** * Returns whether a specified block ID is already registered in the block factory. * * @param int $id + * @param int $variant + * * @return bool */ - public static function isRegistered(int $id) : bool{ - $b = self::$fullList[$id << 4]; + public static function isRegistered(int $id, int $variant = 0) : bool{ + $b = self::$fullList[($id << 4) | $variant]; return $b !== null and !($b instanceof UnknownBlock); } diff --git a/src/pocketmine/block/BoneBlock.php b/src/pocketmine/block/BoneBlock.php index 1eb7e11f5..f632cfcc2 100644 --- a/src/pocketmine/block/BoneBlock.php +++ b/src/pocketmine/block/BoneBlock.php @@ -23,18 +23,20 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\PillarRotationHelper; +use pocketmine\block\utils\PillarRotationTrait; use pocketmine\item\Item; use pocketmine\item\TieredTool; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; class BoneBlock extends Solid{ + use PillarRotationTrait; protected $id = Block::BONE_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ @@ -54,11 +56,7 @@ class BoneBlock extends Solid{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); + $this->axis = Facing::axis($face); return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - - public function getVariantBitmask() : int{ - return 0x03; - } } diff --git a/src/pocketmine/block/Bookshelf.php b/src/pocketmine/block/Bookshelf.php index 3ae90a3ed..417109f64 100644 --- a/src/pocketmine/block/Bookshelf.php +++ b/src/pocketmine/block/Bookshelf.php @@ -30,8 +30,8 @@ class Bookshelf extends Solid{ protected $id = self::BOOKSHELF; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/BrewingStand.php b/src/pocketmine/block/BrewingStand.php index 4d9cc1883..21bbfed48 100644 --- a/src/pocketmine/block/BrewingStand.php +++ b/src/pocketmine/block/BrewingStand.php @@ -32,8 +32,29 @@ class BrewingStand extends Transparent{ protected $itemId = Item::BREWING_STAND; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $eastSlot = false; + /** @var bool */ + protected $northwestSlot = false; + /** @var bool */ + protected $southwestSlot = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return ($this->eastSlot ? 0x01 : 0) | ($this->southwestSlot ? 0x02 : 0) | ($this->northwestSlot ? 0x04 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->eastSlot = ($meta & 0x01) !== 0; + $this->southwestSlot = ($meta & 0x02) !== 0; + $this->northwestSlot = ($meta & 0x04) !== 0; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getName() : string{ @@ -52,9 +73,5 @@ class BrewingStand extends Transparent{ return TieredTool::TIER_WOODEN; } - public function getVariantBitmask() : int{ - return 0; - } - //TODO } diff --git a/src/pocketmine/block/BrickStairs.php b/src/pocketmine/block/BrickStairs.php index 490c2697f..d8fd30393 100644 --- a/src/pocketmine/block/BrickStairs.php +++ b/src/pocketmine/block/BrickStairs.php @@ -29,8 +29,8 @@ class BrickStairs extends Stair{ protected $id = self::BRICK_STAIRS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Bricks.php b/src/pocketmine/block/Bricks.php index f18963ca1..ee50e8d6a 100644 --- a/src/pocketmine/block/Bricks.php +++ b/src/pocketmine/block/Bricks.php @@ -29,8 +29,8 @@ class Bricks extends Solid{ protected $id = self::BRICK_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/BurningFurnace.php b/src/pocketmine/block/BurningFurnace.php deleted file mode 100644 index 2371b1ad2..000000000 --- a/src/pocketmine/block/BurningFurnace.php +++ /dev/null @@ -1,96 +0,0 @@ -setDamage($meta); - } - - public function getName() : string{ - return "Burning Furnace"; - } - - public function getHardness() : float{ - return 3.5; - } - - public function getToolType() : int{ - return BlockToolType::TYPE_PICKAXE; - } - - public function getToolHarvestLevel() : int{ - return TieredTool::TIER_WOODEN; - } - - public function getLightLevel() : int{ - return 13; - } - - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - if($player !== null){ - $this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection())); - } - if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player)); - return true; - } - - return false; - } - - public function onActivate(Item $item, Player $player = null) : bool{ - if($player instanceof Player){ - $furnace = $this->getLevel()->getTile($this); - if(!($furnace instanceof TileFurnace)){ - $furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this)); - } - - if(!$furnace->canOpenWith($item->getCustomName())){ - return true; - } - - $player->addWindow($furnace->getInventory()); - } - - return true; - } - - public function getVariantBitmask() : int{ - return 0; - } -} diff --git a/src/pocketmine/block/Button.php b/src/pocketmine/block/Button.php index 2c1dbaf58..9dc329159 100644 --- a/src/pocketmine/block/Button.php +++ b/src/pocketmine/block/Button.php @@ -24,22 +24,38 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\item\Item; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; abstract class Button extends Flowable{ - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::DOWN; + /** @var bool */ + protected $powered = false; + + public function __construct(){ + } - public function getVariantBitmask() : int{ - return 0; + protected function writeStateToMeta() : int{ + return $this->facing | ($this->powered ? 0x08 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + //TODO: in PC it's (6 - facing) for every meta except 0 (down) + $this->facing = $meta & 0x07; + $this->powered = ($meta & 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->meta = $face; + $this->facing = $face; return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } diff --git a/src/pocketmine/block/Cactus.php b/src/pocketmine/block/Cactus.php index fcf5c4a56..97c10529d 100644 --- a/src/pocketmine/block/Cactus.php +++ b/src/pocketmine/block/Cactus.php @@ -38,8 +38,23 @@ class Cactus extends Transparent{ protected $id = self::CACTUS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $age = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->age; + } + + public function readStateFromMeta(int $meta) : void{ + $this->age = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getHardness() : float{ @@ -85,7 +100,7 @@ class Cactus extends Transparent{ public function onRandomTick() : void{ if($this->getSide(Facing::DOWN)->getId() !== self::CACTUS){ - if($this->meta === 0x0f){ + if($this->age === 15){ for($y = 1; $y < 3; ++$y){ $b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z); if($b->getId() === self::AIR){ @@ -95,10 +110,10 @@ class Cactus extends Transparent{ } } } - $this->meta = 0; + $this->age = 0; $this->getLevel()->setBlock($this, $this); }else{ - ++$this->meta; + ++$this->age; $this->getLevel()->setBlock($this, $this); } } @@ -118,8 +133,4 @@ class Cactus extends Transparent{ return false; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/Cake.php b/src/pocketmine/block/Cake.php index 07de3fc46..f082ba2bd 100644 --- a/src/pocketmine/block/Cake.php +++ b/src/pocketmine/block/Cake.php @@ -38,8 +38,23 @@ class Cake extends Transparent implements FoodSource{ protected $itemId = Item::CAKE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $bites = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->bites; + } + + public function readStateFromMeta(int $meta) : void{ + $this->bites = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getHardness() : float{ @@ -51,7 +66,7 @@ class Cake extends Transparent implements FoodSource{ } protected function recalculateBoundingBox() : ?AxisAlignedBB{ - $f = $this->getDamage() * 0.125; //1 slice width + $f = $this->bites * 0.125; //1 slice width return new AxisAlignedBB( 0.0625 + $f, @@ -112,8 +127,8 @@ class Cake extends Transparent implements FoodSource{ */ public function getResidue(){ $clone = clone $this; - $clone->meta++; - if($clone->meta > 0x06){ + $clone->bites++; + if($clone->bites > 6){ $clone = BlockFactory::get(Block::AIR); } return $clone; diff --git a/src/pocketmine/block/Carpet.php b/src/pocketmine/block/Carpet.php index 92310cc33..b9ca2d13d 100644 --- a/src/pocketmine/block/Carpet.php +++ b/src/pocketmine/block/Carpet.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\ColorBlockMetaHelper; use pocketmine\item\Item; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; @@ -32,12 +31,6 @@ use pocketmine\Player; class Carpet extends Flowable{ - protected $id = self::CARPET; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 0.1; } @@ -46,10 +39,6 @@ class Carpet extends Flowable{ return true; } - public function getName() : string{ - return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Carpet"; - } - protected function recalculateBoundingBox() : ?AxisAlignedBB{ return new AxisAlignedBB(0, 0, 0, 1, 0.0625, 1); } diff --git a/src/pocketmine/block/Carrot.php b/src/pocketmine/block/Carrot.php index 9ca50c224..20af72d1d 100644 --- a/src/pocketmine/block/Carrot.php +++ b/src/pocketmine/block/Carrot.php @@ -30,17 +30,13 @@ class Carrot extends Crops{ protected $id = self::CARROT_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getName() : string{ return "Carrot Block"; } public function getDropsForCompatibleTool(Item $item) : array{ return [ - ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1) + ItemFactory::get(Item::CARROT, 0, $this->age >= 7 ? mt_rand(1, 4) : 1) ]; } diff --git a/src/pocketmine/block/Chest.php b/src/pocketmine/block/Chest.php index ddec85663..a4ccd0522 100644 --- a/src/pocketmine/block/Chest.php +++ b/src/pocketmine/block/Chest.php @@ -36,8 +36,23 @@ class Chest extends Transparent{ protected $id = self::CHEST; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getHardness() : float{ @@ -60,7 +75,7 @@ class Chest extends Transparent{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ $chest = null; if($player !== null){ - $this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection())); + $this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection())); } foreach([ @@ -68,7 +83,7 @@ class Chest extends Transparent{ Bearing::toFacing(Bearing::rotate($player->getDirection(), 1)) ] as $side){ $c = $this->getSide($side); - if($c->getId() === $this->id and $c->getDamage() === $this->meta){ + if($c instanceof Chest and $c->getId() === $this->getId() and $c->facing === $this->facing){ $tile = $this->getLevel()->getTile($c); if($tile instanceof TileChest and !$tile->isPaired()){ $chest = $tile; @@ -116,10 +131,6 @@ class Chest extends Transparent{ return true; } - public function getVariantBitmask() : int{ - return 0; - } - public function getFuelTime() : int{ return 300; } diff --git a/src/pocketmine/block/Clay.php b/src/pocketmine/block/Clay.php index 2fb26fd99..cc279b2be 100644 --- a/src/pocketmine/block/Clay.php +++ b/src/pocketmine/block/Clay.php @@ -30,8 +30,8 @@ class Clay extends Solid{ protected $id = self::CLAY_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Coal.php b/src/pocketmine/block/Coal.php index eb6f609a1..36686bee7 100644 --- a/src/pocketmine/block/Coal.php +++ b/src/pocketmine/block/Coal.php @@ -29,8 +29,8 @@ class Coal extends Solid{ protected $id = self::COAL_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/CoalOre.php b/src/pocketmine/block/CoalOre.php index f440fa2c3..065c391b9 100644 --- a/src/pocketmine/block/CoalOre.php +++ b/src/pocketmine/block/CoalOre.php @@ -31,8 +31,8 @@ class CoalOre extends Solid{ protected $id = self::COAL_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Cobblestone.php b/src/pocketmine/block/Cobblestone.php index dd9cce576..212a85875 100644 --- a/src/pocketmine/block/Cobblestone.php +++ b/src/pocketmine/block/Cobblestone.php @@ -29,8 +29,8 @@ class Cobblestone extends Solid{ protected $id = self::COBBLESTONE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getToolType() : int{ diff --git a/src/pocketmine/block/CobblestoneStairs.php b/src/pocketmine/block/CobblestoneStairs.php index 4670b4957..b67c1a75d 100644 --- a/src/pocketmine/block/CobblestoneStairs.php +++ b/src/pocketmine/block/CobblestoneStairs.php @@ -29,8 +29,8 @@ class CobblestoneStairs extends Stair{ protected $id = self::COBBLESTONE_STAIRS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/CobblestoneWall.php b/src/pocketmine/block/CobblestoneWall.php index 0e2ee42f5..85a2dab8f 100644 --- a/src/pocketmine/block/CobblestoneWall.php +++ b/src/pocketmine/block/CobblestoneWall.php @@ -31,12 +31,6 @@ class CobblestoneWall extends Transparent{ public const NONE_MOSSY_WALL = 0; public const MOSSY_WALL = 1; - protected $id = self::COBBLESTONE_WALL; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } @@ -49,14 +43,6 @@ class CobblestoneWall extends Transparent{ return 2; } - public function getName() : string{ - if($this->meta === 0x01){ - return "Mossy Cobblestone Wall"; - } - - return "Cobblestone Wall"; - } - protected function recalculateBoundingBox() : ?AxisAlignedBB{ //walls don't have any special collision boxes like fences do diff --git a/src/pocketmine/block/Cobweb.php b/src/pocketmine/block/Cobweb.php index d75ee1cfe..cdffe07da 100644 --- a/src/pocketmine/block/Cobweb.php +++ b/src/pocketmine/block/Cobweb.php @@ -31,8 +31,8 @@ class Cobweb extends Flowable{ protected $id = self::COBWEB; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function hasEntityCollision() : bool{ diff --git a/src/pocketmine/block/CocoaBlock.php b/src/pocketmine/block/CocoaBlock.php index 663e8f42c..554533ef8 100644 --- a/src/pocketmine/block/CocoaBlock.php +++ b/src/pocketmine/block/CocoaBlock.php @@ -23,12 +23,38 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\item\Item; +use pocketmine\item\ItemFactory; +use pocketmine\math\AxisAlignedBB; +use pocketmine\math\Bearing; +use pocketmine\math\Facing; +use pocketmine\math\Vector3; +use pocketmine\Player; + class CocoaBlock extends Transparent{ protected $id = self::COCOA_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + /** @var int */ + protected $age = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return Bearing::fromFacing(Facing::opposite($this->facing)) | ($this->age << 2); + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = Facing::opposite(Bearing::toFacing($meta & 0x03)); + $this->age = $meta >> 2; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ diff --git a/src/pocketmine/block/Concrete.php b/src/pocketmine/block/Concrete.php index 42d427a1b..0b8673ab6 100644 --- a/src/pocketmine/block/Concrete.php +++ b/src/pocketmine/block/Concrete.php @@ -23,21 +23,10 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\ColorBlockMetaHelper; use pocketmine\item\TieredTool; class Concrete extends Solid{ - protected $id = Block::CONCRETE; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - - public function getName() : string{ - return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete"; - } - public function getHardness() : float{ return 1.8; } diff --git a/src/pocketmine/block/ConcretePowder.php b/src/pocketmine/block/ConcretePowder.php index a43f688a3..5eff4ef02 100644 --- a/src/pocketmine/block/ConcretePowder.php +++ b/src/pocketmine/block/ConcretePowder.php @@ -23,21 +23,10 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\ColorBlockMetaHelper; use pocketmine\math\Facing; class ConcretePowder extends Fallable{ - protected $id = self::CONCRETE_POWDER; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - - public function getName() : string{ - return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete Powder"; - } - public function getHardness() : float{ return 0.5; } @@ -70,7 +59,7 @@ class ConcretePowder extends Fallable{ continue; } if($this->getSide($i) instanceof Water){ - return BlockFactory::get(Block::CONCRETE, $this->meta); + return BlockFactory::get(Block::CONCRETE, $this->variant); } } diff --git a/src/pocketmine/block/CraftingTable.php b/src/pocketmine/block/CraftingTable.php index a0ce8ce3b..1576e389d 100644 --- a/src/pocketmine/block/CraftingTable.php +++ b/src/pocketmine/block/CraftingTable.php @@ -31,8 +31,8 @@ class CraftingTable extends Solid{ protected $id = self::CRAFTING_TABLE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Crops.php b/src/pocketmine/block/Crops.php index f92f94add..e890fa3dd 100644 --- a/src/pocketmine/block/Crops.php +++ b/src/pocketmine/block/Crops.php @@ -31,6 +31,24 @@ use pocketmine\Player; use pocketmine\Server; abstract class Crops extends Flowable{ + /** @var int */ + protected $age = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->age; + } + + public function readStateFromMeta(int $meta) : void{ + $this->age = $meta; + } + + 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){ @@ -44,9 +62,9 @@ abstract class Crops extends Flowable{ public function onActivate(Item $item, Player $player = null) : bool{ if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal $block = clone $this; - $block->meta += mt_rand(2, 5); - if($block->meta > 7){ - $block->meta = 7; + $block->age += mt_rand(2, 5); + if($block->age > 7){ + $block->age = 7; } Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block)); @@ -75,9 +93,9 @@ abstract class Crops extends Flowable{ public function onRandomTick() : void{ if(mt_rand(0, 2) === 1){ - if($this->meta < 0x07){ + if($this->age < 7){ $block = clone $this; - ++$block->meta; + ++$block->age; Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block)); if(!$ev->isCancelled()){ diff --git a/src/pocketmine/block/Dandelion.php b/src/pocketmine/block/Dandelion.php index 50b887d93..15be4a871 100644 --- a/src/pocketmine/block/Dandelion.php +++ b/src/pocketmine/block/Dandelion.php @@ -32,8 +32,8 @@ class Dandelion extends Flowable{ protected $id = self::DANDELION; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/DaylightSensor.php b/src/pocketmine/block/DaylightSensor.php index 708667600..7ffe1377e 100644 --- a/src/pocketmine/block/DaylightSensor.php +++ b/src/pocketmine/block/DaylightSensor.php @@ -25,10 +25,40 @@ namespace pocketmine\block; class DaylightSensor extends Transparent{ - protected $id = self::DAYLIGHT_SENSOR; + protected $itemId = self::DAYLIGHT_SENSOR; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $power = 0; + + /** @var bool */ + protected $inverted = false; + + public function __construct(){ + + } + + public function getId() : int{ + return $this->inverted ? self::DAYLIGHT_SENSOR_INVERTED : self::DAYLIGHT_SENSOR; + } + + protected function writeStateToMeta() : int{ + return $this->power; + } + + public function readStateFromMeta(int $meta) : void{ + $this->power = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; + } + + public function isInverted() : bool{ + return $this->inverted; + } + + public function setInverted(bool $inverted = true) : void{ + $this->inverted = $inverted; } public function getName() : string{ diff --git a/src/pocketmine/block/DeadBush.php b/src/pocketmine/block/DeadBush.php index d32afc18c..9cfd5a51d 100644 --- a/src/pocketmine/block/DeadBush.php +++ b/src/pocketmine/block/DeadBush.php @@ -33,8 +33,8 @@ class DeadBush extends Flowable{ protected $id = self::DEAD_BUSH; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Diamond.php b/src/pocketmine/block/Diamond.php index 3a6f66aa7..83a7935b6 100644 --- a/src/pocketmine/block/Diamond.php +++ b/src/pocketmine/block/Diamond.php @@ -29,8 +29,8 @@ class Diamond extends Solid{ protected $id = self::DIAMOND_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/DiamondOre.php b/src/pocketmine/block/DiamondOre.php index a789d9d45..a6a057607 100644 --- a/src/pocketmine/block/DiamondOre.php +++ b/src/pocketmine/block/DiamondOre.php @@ -31,8 +31,8 @@ class DiamondOre extends Solid{ protected $id = self::DIAMOND_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Dirt.php b/src/pocketmine/block/Dirt.php index 89a4e519d..fea10f3e2 100644 --- a/src/pocketmine/block/Dirt.php +++ b/src/pocketmine/block/Dirt.php @@ -28,12 +28,8 @@ use pocketmine\item\Item; use pocketmine\Player; class Dirt extends Solid{ - - protected $id = self::DIRT; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } + public const NORMAL = 0; + public const COARSE = 1; public function getHardness() : float{ return 0.5; @@ -43,17 +39,10 @@ class Dirt extends Solid{ return BlockToolType::TYPE_SHOVEL; } - public function getName() : string{ - if($this->meta === 1){ - return "Coarse Dirt"; - } - return "Dirt"; - } - public function onActivate(Item $item, Player $player = null) : bool{ if($item instanceof Hoe){ $item->applyDamage(1); - if($this->meta === 1){ + if($this->variant === self::COARSE){ $this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true); }else{ $this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true); diff --git a/src/pocketmine/block/Door.php b/src/pocketmine/block/Door.php index a0371f49e..31edd423d 100644 --- a/src/pocketmine/block/Door.php +++ b/src/pocketmine/block/Door.php @@ -33,41 +33,72 @@ use pocketmine\Player; abstract class Door extends Transparent{ + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $top = false; + /** @var bool */ + protected $hingeRight = false; + + /** @var bool */ + protected $open = false; + /** @var bool */ + protected $powered = false; + + + protected function writeStateToMeta() : int{ + if($this->top){ + return 0x08 | ($this->hingeRight ? 0x01 : 0) | ($this->powered ? 0x02 : 0); + } + + return Bearing::rotate(Bearing::fromFacing($this->facing), 1) | ($this->open ? 0x04 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->top = $meta & 0x08; + if($this->top){ + $this->hingeRight = ($meta & 0x01) !== 0; + $this->powered = ($meta & 0x02) !== 0; + }else{ + $this->facing = Bearing::toFacing(Bearing::rotate($meta & 0x03, -1)); + $this->open = ($meta & 0x04) !== 0; + } + } + + public function getStateBitmask() : int{ + return 0b1111; + } + + /** + * Copies door properties from the other half of the door, since metadata is split between the two halves. + * TODO: the blockstate should be updated directly on creation so these properties can be detected in advance. + */ + private function updateStateFromOtherHalf() : void{ + $other = $this->getSide($this->top ? Facing::DOWN : Facing::UP); + if($other instanceof Door and $other->getId() === $this->getId()){ + if($this->top){ + $this->facing = $other->facing; + $this->open = $other->open; + }else{ + $this->hingeRight = $other->hingeRight; + $this->powered = $other->powered; + } + } + } public function isSolid() : bool{ return false; } - private function getFullDamage(){ - $damage = $this->getDamage(); - $isUp = ($damage & 0x08) > 0; - - if($isUp){ - $down = $this->getSide(Facing::DOWN)->getDamage(); - $up = $damage; - }else{ - $down = $damage; - $up = $this->getSide(Facing::UP)->getDamage(); - } - - $isRight = ($up & 0x01) > 0; - - return $down & 0x07 | ($isUp ? 8 : 0) | ($isRight ? 0x10 : 0); - } - protected function recalculateBoundingBox() : ?AxisAlignedBB{ $f = 0.1875; - $damage = $this->getFullDamage(); + $this->updateStateFromOtherHalf(); $bb = new AxisAlignedBB(0, 0, 0, 1, 2, 1); - $j = $damage & 0x03; - $isOpen = (($damage & 0x04) > 0); - $isRight = (($damage & 0x10) > 0); - - if($j === 0){ - if($isOpen){ - if(!$isRight){ + if($this->facing === Facing::EAST){ + if($this->open){ + if(!$this->hingeRight){ $bb->setBounds(0, 0, 0, 1, 1, $f); }else{ $bb->setBounds(0, 0, 1 - $f, 1, 1, 1); @@ -75,9 +106,9 @@ abstract class Door extends Transparent{ }else{ $bb->setBounds(0, 0, 0, $f, 1, 1); } - }elseif($j === 1){ - if($isOpen){ - if(!$isRight){ + }elseif($this->facing === Facing::SOUTH){ + if($this->open){ + if(!$this->hingeRight){ $bb->setBounds(1 - $f, 0, 0, 1, 1, 1); }else{ $bb->setBounds(0, 0, 0, $f, 1, 1); @@ -85,9 +116,9 @@ abstract class Door extends Transparent{ }else{ $bb->setBounds(0, 0, 0, 1, 1, $f); } - }elseif($j === 2){ - if($isOpen){ - if(!$isRight){ + }elseif($this->facing === Facing::WEST){ + if($this->open){ + if(!$this->hingeRight){ $bb->setBounds(0, 0, 1 - $f, 1, 1, 1); }else{ $bb->setBounds(0, 0, 0, 1, 1, $f); @@ -95,9 +126,9 @@ abstract class Door extends Transparent{ }else{ $bb->setBounds(1 - $f, 0, 0, 1, 1, 1); } - }elseif($j === 3){ - if($isOpen){ - if(!$isRight){ + }elseif($this->facing === Facing::NORTH){ + if($this->open){ + if(!$this->hingeRight){ $bb->setBounds(0, 0, 0, $f, 1, 1); }else{ $bb->setBounds(1 - $f, 0, 0, 1, 1, 1); @@ -127,21 +158,22 @@ abstract class Door extends Transparent{ return false; } - //door faces this way when opened (unless it's right, in which case it's the opposite) - $direction = $player !== null ? Bearing::rotate($player->getDirection(), 1) : Bearing::NORTH; - - $facing = Bearing::toFacing($direction); - $next = $this->getSide(Facing::opposite($facing)); - $next2 = $this->getSide($facing); - - $metaUp = 0x08; - if($next->getId() === $this->getId() or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge - $metaUp |= 0x01; + if($player !== null){ + $this->facing = Bearing::toFacing($player->getDirection()); } - $this->setDamage($direction); + $next = $this->getSide(Facing::rotate($this->facing, Facing::AXIS_Y, false)); + $next2 = $this->getSide(Facing::rotate($this->facing, Facing::AXIS_Y, true)); + + if($next->getId() === $this->getId() or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge + $this->hingeRight = true; + } + + $topHalf = clone $this; + $topHalf->top = true; + parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); - $this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top + $this->level->setBlock($blockUp, $topHalf, true); //Top return true; } @@ -149,31 +181,23 @@ abstract class Door extends Transparent{ } public function onActivate(Item $item, Player $player = null) : bool{ - if(($this->getDamage() & 0x08) === 0x08){ //Top - $down = $this->getSide(Facing::DOWN); - if($down->getId() === $this->getId()){ - $meta = $down->getDamage() ^ 0x04; - $this->level->setBlock($down, BlockFactory::get($this->getId(), $meta), true); - $this->level->addSound(new DoorSound($this)); - return true; - } + $this->updateStateFromOtherHalf(); + $this->open = !$this->open; - return false; - }else{ - $this->meta ^= 0x04; - $this->level->setBlock($this, $this, true); - $this->level->addSound(new DoorSound($this)); + $other = $this->getSide($this->top ? Facing::DOWN : Facing::UP); + if($other instanceof Door and $this->getId() === $other->getId()){ + $other->open = $this->open; + $this->level->setBlock($other, $other, true, true); } + $this->level->setBlock($this, $this, true, true); + $this->level->addSound(new DoorSound($this)); + return true; } - public function getVariantBitmask() : int{ - return 0; - } - public function getDropsForCompatibleTool(Item $item) : array{ - if(($this->meta & 0x08) === 0){ //bottom half only + if(!$this->top){ //bottom half only return parent::getDropsForCompatibleTool($item); } @@ -185,18 +209,10 @@ abstract class Door extends Transparent{ } public function getAffectedBlocks() : array{ - if(($this->getDamage() & 0x08) === 0x08){ - $down = $this->getSide(Facing::DOWN); - if($down->getId() === $this->getId()){ - return [$this, $down]; - } - }else{ - $up = $this->getSide(Facing::UP); - if($up->getId() === $this->getId()){ - return [$this, $up]; - } + $other = $this->getSide($this->top ? Facing::DOWN : Facing::UP); + if($other->getId() === $this->getId()){ + return [$this, $other]; } - return parent::getAffectedBlocks(); } } diff --git a/src/pocketmine/block/DoublePlant.php b/src/pocketmine/block/DoublePlant.php index 1c9317de5..8f11b1e9c 100644 --- a/src/pocketmine/block/DoublePlant.php +++ b/src/pocketmine/block/DoublePlant.php @@ -30,35 +30,34 @@ use pocketmine\math\Vector3; use pocketmine\Player; class DoublePlant extends Flowable{ - public const BITFLAG_TOP = 0x08; + private const BITFLAG_TOP = 0x08; - protected $id = self::DOUBLE_PLANT; + /** @var bool */ + protected $top = false; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + protected function writeStateToMeta() : int{ + return ($this->top ? self::BITFLAG_TOP : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->top = ($meta & self::BITFLAG_TOP) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1000; } public function canBeReplaced() : bool{ - return $this->meta === 2 or $this->meta === 3; //grass or fern - } - - public function getName() : string{ - static $names = [ - 0 => "Sunflower", - 1 => "Lilac", - 2 => "Double Tallgrass", - 3 => "Large Fern", - 4 => "Rose Bush", - 5 => "Peony" - ]; - return $names[$this->getVariant()] ?? ""; + return $this->variant === 2 or $this->variant === 3; //grass or fern } 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()){ $this->getLevel()->setBlock($blockReplace, $this, false, false); - $this->getLevel()->setBlock($blockReplace->getSide(Facing::UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false); + $top = clone $this; + $top->top = true; + $this->getLevel()->setBlock($blockReplace->getSide(Facing::UP), $top, false, false); return true; } @@ -71,39 +70,32 @@ class DoublePlant extends Flowable{ * @return bool */ public function isValidHalfPlant() : bool{ - if($this->meta & self::BITFLAG_TOP){ - $other = $this->getSide(Facing::DOWN); - }else{ - $other = $this->getSide(Facing::UP); - } + $other = $this->getSide($this->top ? Facing::DOWN : Facing::UP); return ( + $other instanceof DoublePlant and $other->getId() === $this->getId() and - $other->getVariant() === $this->getVariant() and - ($other->getDamage() & self::BITFLAG_TOP) !== ($this->getDamage() & self::BITFLAG_TOP) + $other->getVariant() === $this->variant and + $other->top !== $this->top ); } public function onNearbyBlockChange() : void{ - if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Facing::DOWN)->isTransparent())){ + if(!$this->isValidHalfPlant() or (!$this->top and $this->getSide(Facing::DOWN)->isTransparent())){ $this->getLevel()->useBreakOn($this); } } - public function getVariantBitmask() : int{ - return 0x07; - } - public function getToolType() : int{ - return ($this->meta === 2 or $this->meta === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE; + return ($this->variant === 2 or $this->variant === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE; } public function getToolHarvestLevel() : int{ - return ($this->meta === 2 or $this->meta === 3) ? 1 : 0; //only grass or fern require shears + return ($this->variant === 2 or $this->variant === 3) ? 1 : 0; //only grass or fern require shears } public function getDrops(Item $item) : array{ - if($this->meta & self::BITFLAG_TOP){ + if($this->top){ if($this->isCompatibleWithTool($item)){ return parent::getDrops($item); } @@ -120,7 +112,7 @@ class DoublePlant extends Flowable{ public function getAffectedBlocks() : array{ if($this->isValidHalfPlant()){ - return [$this, $this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Facing::DOWN : Facing::UP)]; + return [$this, $this->getSide($this->top ? Facing::DOWN : Facing::UP)]; } return parent::getAffectedBlocks(); diff --git a/src/pocketmine/block/DoubleSlab.php b/src/pocketmine/block/DoubleSlab.php index 02006099b..acdbb887c 100644 --- a/src/pocketmine/block/DoubleSlab.php +++ b/src/pocketmine/block/DoubleSlab.php @@ -26,21 +26,46 @@ namespace pocketmine\block; use pocketmine\item\Item; use pocketmine\item\ItemFactory; -abstract class DoubleSlab extends Solid{ +class DoubleSlab extends Solid{ + /** @var int */ + protected $singleId; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(int $id, int $singleId, int $variant = 0){ + parent::__construct($id, $variant); + $this->singleId = $singleId; } - abstract public function getSlabId() : int; + protected function getSingle() : Block{ + return BlockFactory::get($this->singleId, $this->variant); + } + + public function getHardness() : float{ + return $this->getSingle()->getHardness(); + } + + public function getToolType() : int{ + return $this->getSingle()->getToolType(); + } + + public function getToolHarvestLevel() : int{ + return $this->getSingle()->getToolHarvestLevel(); + } + + public function getFlameEncouragement() : int{ + return $this->getSingle()->getFlameEncouragement(); + } + + public function getFlammability() : int{ + return $this->getSingle()->getFlammability(); + } public function getName() : string{ - return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName(); + return "Double " . $this->getSingle()->getName(); } public function getDropsForCompatibleTool(Item $item) : array{ return [ - ItemFactory::get($this->getSlabId(), $this->getVariant(), 2) + ItemFactory::get($this->singleId, $this->variant, 2) ]; } diff --git a/src/pocketmine/block/DoubleStoneSlab.php b/src/pocketmine/block/DoubleStoneSlab.php deleted file mode 100644 index 1466828ea..000000000 --- a/src/pocketmine/block/DoubleStoneSlab.php +++ /dev/null @@ -1,47 +0,0 @@ -setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/EmeraldOre.php b/src/pocketmine/block/EmeraldOre.php index 31c2a3f80..7c94475ea 100644 --- a/src/pocketmine/block/EmeraldOre.php +++ b/src/pocketmine/block/EmeraldOre.php @@ -31,8 +31,8 @@ class EmeraldOre extends Solid{ protected $id = self::EMERALD_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/EnchantingTable.php b/src/pocketmine/block/EnchantingTable.php index 4a23b3ab1..0b0d066c2 100644 --- a/src/pocketmine/block/EnchantingTable.php +++ b/src/pocketmine/block/EnchantingTable.php @@ -35,8 +35,8 @@ class EnchantingTable extends Transparent{ protected $id = self::ENCHANTING_TABLE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ diff --git a/src/pocketmine/block/EndPortalFrame.php b/src/pocketmine/block/EndPortalFrame.php index 193788054..5c002b71f 100644 --- a/src/pocketmine/block/EndPortalFrame.php +++ b/src/pocketmine/block/EndPortalFrame.php @@ -25,13 +25,35 @@ namespace pocketmine\block; use pocketmine\item\Item; use pocketmine\math\AxisAlignedBB; +use pocketmine\math\Bearing; +use pocketmine\math\Facing; +use pocketmine\math\Vector3; +use pocketmine\Player; class EndPortalFrame extends Solid{ protected $id = self::END_PORTAL_FRAME; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $eye = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return Bearing::fromFacing($this->facing) | ($this->eye ? 0x04 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = Bearing::toFacing($meta & 0x03); + $this->eye = ($meta & 0x04) !== 0; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getLightLevel() : int{ @@ -55,14 +77,20 @@ class EndPortalFrame extends Solid{ } protected function recalculateBoundingBox() : ?AxisAlignedBB{ - return new AxisAlignedBB( 0, 0, 0, 1, - (($this->getDamage() & 0x04) > 0 ? 1 : 0.8125), + $this->eye ? 1 : 0.8125, 1 ); } + + public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ + if($player !== null){ + $this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection())); + } + return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); + } } diff --git a/src/pocketmine/block/EndRod.php b/src/pocketmine/block/EndRod.php index 306cdd266..25391667b 100644 --- a/src/pocketmine/block/EndRod.php +++ b/src/pocketmine/block/EndRod.php @@ -33,8 +33,30 @@ class EndRod extends Flowable{ protected $id = Block::END_ROD; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::DOWN; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + if(Facing::axis($this->facing) === Facing::AXIS_Y){ + return $this->facing; + } + return $this->facing ^ 1; //TODO: in PC this is always the same as facing, just PE is stupid + } + + public function readStateFromMeta(int $meta) : void{ + if($meta === 0 or $meta === 1){ + $this->facing = $meta; + }else{ + $this->facing = $meta ^ 1; //TODO: see above + } + } + + public function getStateBitmask() : int{ + return 0b111; } public function getName() : string{ @@ -42,13 +64,9 @@ class EndRod extends Flowable{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - if(Facing::axis($face) === Facing::AXIS_Y){ - $this->meta = $face; - }else{ - $this->meta = $face ^ 0x01; - } - if($blockClicked instanceof EndRod and $blockClicked->getDamage() === $this->meta){ - $this->meta ^= 0x01; + $this->facing = $face; + if($blockClicked instanceof EndRod and $blockClicked->facing === $this->facing){ + $this->facing = Facing::opposite($face); } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); @@ -63,7 +81,7 @@ class EndRod extends Flowable{ } protected function recalculateBoundingBox() : ?AxisAlignedBB{ - $m = $this->meta >> 1; //everything except up/down are inverted, but we can still use this for axis + $m = Facing::axis($this->facing); $width = 0.375; switch($m){ @@ -98,8 +116,4 @@ class EndRod extends Flowable{ return null; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/EndStone.php b/src/pocketmine/block/EndStone.php index cd4f40c7d..17953f776 100644 --- a/src/pocketmine/block/EndStone.php +++ b/src/pocketmine/block/EndStone.php @@ -29,8 +29,8 @@ class EndStone extends Solid{ protected $id = self::END_STONE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/EndStoneBricks.php b/src/pocketmine/block/EndStoneBricks.php index a925f952c..0808f18b1 100644 --- a/src/pocketmine/block/EndStoneBricks.php +++ b/src/pocketmine/block/EndStoneBricks.php @@ -29,8 +29,8 @@ class EndStoneBricks extends Solid{ protected $id = self::END_BRICKS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/EnderChest.php b/src/pocketmine/block/EnderChest.php index 348c5c701..8bf91e201 100644 --- a/src/pocketmine/block/EnderChest.php +++ b/src/pocketmine/block/EnderChest.php @@ -62,8 +62,8 @@ class EnderChest extends Chest{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - if($player !== null){ - $this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection())); + if($player !== null){ //same as normal chest - TODO: clean up inheritance here + $this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection())); } if(Block::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ diff --git a/src/pocketmine/block/Farmland.php b/src/pocketmine/block/Farmland.php index 0b435b114..0db8a649a 100644 --- a/src/pocketmine/block/Farmland.php +++ b/src/pocketmine/block/Farmland.php @@ -32,8 +32,23 @@ class Farmland extends Transparent{ protected $id = self::FARMLAND; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $wetness = 0; //"moisture" blockstate property in PC + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->wetness; + } + + public function readStateFromMeta(int $meta) : void{ + $this->wetness = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getName() : string{ @@ -64,14 +79,14 @@ class Farmland extends Transparent{ public function onRandomTick() : void{ if(!$this->canHydrate()){ - if($this->meta > 0){ - $this->meta--; + if($this->wetness > 0){ + $this->wetness--; $this->level->setBlock($this, $this, false, false); }else{ $this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true); } - }elseif($this->meta < 7){ - $this->meta = 7; + }elseif($this->wetness < 7){ + $this->wetness = 7; $this->level->setBlock($this, $this, false, false); } } diff --git a/src/pocketmine/block/Fence.php b/src/pocketmine/block/Fence.php index effd3b824..b207619c6 100644 --- a/src/pocketmine/block/Fence.php +++ b/src/pocketmine/block/Fence.php @@ -28,10 +28,6 @@ use pocketmine\math\Facing; abstract class Fence extends Transparent{ - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getThickness() : float{ return 0.25; } diff --git a/src/pocketmine/block/FenceGate.php b/src/pocketmine/block/FenceGate.php index e3e3191b9..5f14cdcd7 100644 --- a/src/pocketmine/block/FenceGate.php +++ b/src/pocketmine/block/FenceGate.php @@ -26,10 +26,29 @@ namespace pocketmine\block; use pocketmine\item\Item; use pocketmine\level\sound\DoorSound; use pocketmine\math\AxisAlignedBB; +use pocketmine\math\Bearing; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; class FenceGate extends Transparent{ + /** @var bool */ + protected $open = false; + /** @var int */ + protected $facing = Facing::NORTH; + + protected function writeStateToMeta() : int{ + return Bearing::fromFacing($this->facing) | ($this->open ? 0x04 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = Bearing::toFacing($meta & 0x03); + $this->open = ($meta & 0x04) !== 0; + } + + public function getStateBitmask() : int{ + return 0b111; + } public function getHardness() : float{ return 2; @@ -41,12 +60,11 @@ class FenceGate extends Transparent{ protected function recalculateBoundingBox() : ?AxisAlignedBB{ - if(($this->getDamage() & 0x04) > 0){ + if($this->open){ return null; } - $i = ($this->getDamage() & 0x03); - if($i === 2 or $i === 0){ + if(Facing::axis($this->facing) === Facing::AXIS_Z){ return new AxisAlignedBB( 0, 0, @@ -69,21 +87,19 @@ class FenceGate extends Transparent{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if($player !== null){ - $this->meta = $player->getDirection(); + $this->facing = Bearing::toFacing($player->getDirection()); } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - public function getVariantBitmask() : int{ - return 0; - } - public function onActivate(Item $item, Player $player = null) : bool{ - $this->meta = (($this->meta ^ 0x04) & ~0x02); - - if($player !== null){ - $this->meta |= ($player->getDirection() & 0x02); //open towards the player, retaining axis + $this->open = !$this->open; + if($this->open and $player !== null){ + $playerFacing = Bearing::toFacing($player->getDirection()); + if($playerFacing === Facing::opposite($this->facing)){ + $this->facing = $playerFacing; + } } $this->getLevel()->setBlock($this, $this, true); diff --git a/src/pocketmine/block/Fire.php b/src/pocketmine/block/Fire.php index a6bd4c1e7..7aa4abd1f 100644 --- a/src/pocketmine/block/Fire.php +++ b/src/pocketmine/block/Fire.php @@ -37,8 +37,23 @@ class Fire extends Flowable{ protected $id = self::FIRE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $age = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->age; + } + + public function readStateFromMeta(int $meta) : void{ + $this->age = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function hasEntityCollision() : bool{ @@ -95,22 +110,22 @@ class Fire extends Flowable{ $down = $this->getSide(Facing::DOWN); $result = null; - if($this->meta < 15 and mt_rand(0, 2) === 0){ - $this->meta++; + if($this->age < 15 and mt_rand(0, 2) === 0){ + $this->age++; $result = $this; } $canSpread = true; if(!$down->burnsForever()){ //TODO: check rain - if($this->meta === 15){ + if($this->age === 15){ if(!$down->isFlammable() and mt_rand(0, 3) === 3){ //1/4 chance to extinguish $canSpread = false; $result = BlockFactory::get(Block::AIR); } }elseif(!$this->hasAdjacentFlammableBlocks()){ $canSpread = false; - if(!$down->isSolid() or $this->meta > 3){ //fire older than 3, or without a solid block below + if(!$down->isSolid() or $this->age > 3){ $result = BlockFactory::get(Block::AIR); } } @@ -157,8 +172,10 @@ class Fire extends Flowable{ if(!$ev->isCancelled()){ $block->onIncinerate(); - if(mt_rand(0, $this->meta + 9) < 5){ //TODO: check rain - $this->level->setBlock($block, BlockFactory::get(Block::FIRE, min(15, $this->meta + (mt_rand(0, 4) >> 2)))); + if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain + $fire = clone $this; + $fire->age = min(15, $fire->age + (mt_rand(0, 4) >> 2)); + $this->level->setBlock($block, $fire); }else{ $this->level->setBlock($block, BlockFactory::get(Block::AIR)); } diff --git a/src/pocketmine/block/Flower.php b/src/pocketmine/block/Flower.php index fb85cbefb..4ae18ae68 100644 --- a/src/pocketmine/block/Flower.php +++ b/src/pocketmine/block/Flower.php @@ -39,27 +39,6 @@ class Flower extends Flowable{ public const TYPE_PINK_TULIP = 7; public const TYPE_OXEYE_DAISY = 8; - protected $id = self::RED_FLOWER; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - - public function getName() : string{ - static $names = [ - self::TYPE_POPPY => "Poppy", - self::TYPE_BLUE_ORCHID => "Blue Orchid", - self::TYPE_ALLIUM => "Allium", - self::TYPE_AZURE_BLUET => "Azure Bluet", - self::TYPE_RED_TULIP => "Red Tulip", - self::TYPE_ORANGE_TULIP => "Orange Tulip", - self::TYPE_WHITE_TULIP => "White Tulip", - self::TYPE_PINK_TULIP => "Pink Tulip", - self::TYPE_OXEYE_DAISY => "Oxeye Daisy" - ]; - return $names[$this->meta] ?? "Unknown"; - } - 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::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){ diff --git a/src/pocketmine/block/FlowerPot.php b/src/pocketmine/block/FlowerPot.php index 40555546c..2a07fd07d 100644 --- a/src/pocketmine/block/FlowerPot.php +++ b/src/pocketmine/block/FlowerPot.php @@ -33,14 +33,26 @@ use pocketmine\tile\Tile; class FlowerPot extends Flowable{ - public const STATE_EMPTY = 0; - public const STATE_FULL = 1; - protected $id = self::FLOWER_POT_BLOCK; protected $itemId = Item::FLOWER_POT; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $occupied = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->occupied ? 1 : 0; + } + + public function readStateFromMeta(int $meta) : void{ + $this->occupied = $meta !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; //vanilla uses various values, we only care about 1 and 0 for PE } public function getName() : string{ @@ -80,17 +92,13 @@ class FlowerPot extends Flowable{ return true; } - $this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item. + $this->occupied = true; $this->getLevel()->setBlock($this, $this, true, false); $pot->setItem($item->pop()); return true; } - public function getVariantBitmask() : int{ - return 0; - } - public function getDropsForCompatibleTool(Item $item) : array{ $items = parent::getDropsForCompatibleTool($item); diff --git a/src/pocketmine/block/Furnace.php b/src/pocketmine/block/Furnace.php index eb8acd9ed..a31135579 100644 --- a/src/pocketmine/block/Furnace.php +++ b/src/pocketmine/block/Furnace.php @@ -23,16 +23,98 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\item\Item; +use pocketmine\item\TieredTool; +use pocketmine\math\Bearing; +use pocketmine\math\Facing; +use pocketmine\math\Vector3; +use pocketmine\Player; +use pocketmine\tile\Furnace as TileFurnace; +use pocketmine\tile\Tile; -class Furnace extends BurningFurnace{ +class Furnace extends Solid{ - protected $id = self::FURNACE; + protected $itemId = self::FURNACE; + + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $lit = false; //this is set based on the blockID + + public function __construct(){ + + } + + public function getId() : int{ + return $this->lit ? Block::BURNING_FURNACE : Block::FURNACE; + } + + protected function writeStateToMeta() : int{ + return $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; + } public function getName() : string{ return "Furnace"; } + public function getHardness() : float{ + return 3.5; + } + + public function getToolType() : int{ + return BlockToolType::TYPE_PICKAXE; + } + + public function getToolHarvestLevel() : int{ + return TieredTool::TIER_WOODEN; + } + public function getLightLevel() : int{ - return 0; + return $this->lit ? 13 : 0; + } + + public function isLit() : bool{ + return $this->lit; + } + + public function setLit(bool $lit = true) : void{ + $this->lit = $lit; + } + + public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ + if($player !== null){ + $this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection())); + } + if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ + Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player)); + return true; + } + + return false; + } + + public function onActivate(Item $item, Player $player = null) : bool{ + if($player instanceof Player){ + $furnace = $this->getLevel()->getTile($this); + if(!($furnace instanceof TileFurnace)){ + $furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this)); + } + + if(!$furnace->canOpenWith($item->getCustomName())){ + return true; + } + + $player->addWindow($furnace->getInventory()); + } + + return true; } } diff --git a/src/pocketmine/block/Glass.php b/src/pocketmine/block/Glass.php index 65ab80b57..dd25ea742 100644 --- a/src/pocketmine/block/Glass.php +++ b/src/pocketmine/block/Glass.php @@ -27,16 +27,6 @@ use pocketmine\item\Item; class Glass extends Transparent{ - protected $id = self::GLASS; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - - public function getName() : string{ - return "Glass"; - } - public function getHardness() : float{ return 0.3; } diff --git a/src/pocketmine/block/GlassPane.php b/src/pocketmine/block/GlassPane.php index cc1944067..7f2e02fd6 100644 --- a/src/pocketmine/block/GlassPane.php +++ b/src/pocketmine/block/GlassPane.php @@ -27,16 +27,6 @@ use pocketmine\item\Item; class GlassPane extends Thin{ - protected $id = self::GLASS_PANE; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - - public function getName() : string{ - return "Glass Pane"; - } - public function getHardness() : float{ return 0.3; } diff --git a/src/pocketmine/block/GlazedTerracotta.php b/src/pocketmine/block/GlazedTerracotta.php index 803527475..f3b5e72c5 100644 --- a/src/pocketmine/block/GlazedTerracotta.php +++ b/src/pocketmine/block/GlazedTerracotta.php @@ -27,11 +27,27 @@ namespace pocketmine\block; use pocketmine\item\Item; use pocketmine\item\TieredTool; use pocketmine\math\Bearing; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; class GlazedTerracotta extends Solid{ + /** @var int */ + protected $facing = Facing::NORTH; + + protected function writeStateToMeta() : int{ + return $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; + } + public function getHardness() : float{ return 1.4; } @@ -46,13 +62,9 @@ class GlazedTerracotta extends Solid{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if($player !== null){ - $this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection())); + $this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection())); } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/GlowingObsidian.php b/src/pocketmine/block/GlowingObsidian.php index e8e62a76d..51e81c450 100644 --- a/src/pocketmine/block/GlowingObsidian.php +++ b/src/pocketmine/block/GlowingObsidian.php @@ -30,8 +30,8 @@ class GlowingObsidian extends Solid{ protected $id = self::GLOWING_OBSIDIAN; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/GlowingRedstoneOre.php b/src/pocketmine/block/GlowingRedstoneOre.php deleted file mode 100644 index 0825bf546..000000000 --- a/src/pocketmine/block/GlowingRedstoneOre.php +++ /dev/null @@ -1,58 +0,0 @@ -getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false); - } -} diff --git a/src/pocketmine/block/Glowstone.php b/src/pocketmine/block/Glowstone.php index 02f5a31ba..c4ab959fe 100644 --- a/src/pocketmine/block/Glowstone.php +++ b/src/pocketmine/block/Glowstone.php @@ -30,8 +30,8 @@ class Glowstone extends Transparent{ protected $id = self::GLOWSTONE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Gold.php b/src/pocketmine/block/Gold.php index 99e82324a..8e6aa97c2 100644 --- a/src/pocketmine/block/Gold.php +++ b/src/pocketmine/block/Gold.php @@ -29,8 +29,8 @@ class Gold extends Solid{ protected $id = self::GOLD_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/GoldOre.php b/src/pocketmine/block/GoldOre.php index a6b280ccf..9ef07f4cc 100644 --- a/src/pocketmine/block/GoldOre.php +++ b/src/pocketmine/block/GoldOre.php @@ -29,8 +29,8 @@ class GoldOre extends Solid{ protected $id = self::GOLD_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Grass.php b/src/pocketmine/block/Grass.php index 641f3118e..954c5f9ba 100644 --- a/src/pocketmine/block/Grass.php +++ b/src/pocketmine/block/Grass.php @@ -37,8 +37,8 @@ class Grass extends Solid{ protected $id = self::GRASS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/GrassPath.php b/src/pocketmine/block/GrassPath.php index 18818277f..9ec3737af 100644 --- a/src/pocketmine/block/GrassPath.php +++ b/src/pocketmine/block/GrassPath.php @@ -32,8 +32,8 @@ class GrassPath extends Transparent{ protected $id = self::GRASS_PATH; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Gravel.php b/src/pocketmine/block/Gravel.php index d2492729b..a5ee8d07d 100644 --- a/src/pocketmine/block/Gravel.php +++ b/src/pocketmine/block/Gravel.php @@ -30,8 +30,8 @@ class Gravel extends Fallable{ protected $id = self::GRAVEL; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/HardenedClay.php b/src/pocketmine/block/HardenedClay.php index 7918c2c32..77b06e2a3 100644 --- a/src/pocketmine/block/HardenedClay.php +++ b/src/pocketmine/block/HardenedClay.php @@ -27,16 +27,6 @@ use pocketmine\item\TieredTool; class HardenedClay extends Solid{ - protected $id = self::HARDENED_CLAY; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - - public function getName() : string{ - return "Hardened Clay"; - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } diff --git a/src/pocketmine/block/HayBale.php b/src/pocketmine/block/HayBale.php index 696c8c8f9..e39f20003 100644 --- a/src/pocketmine/block/HayBale.php +++ b/src/pocketmine/block/HayBale.php @@ -23,17 +23,19 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\PillarRotationHelper; +use pocketmine\block\utils\PillarRotationTrait; use pocketmine\item\Item; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; class HayBale extends Solid{ + use PillarRotationTrait; protected $id = self::HAY_BALE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ @@ -45,14 +47,10 @@ class HayBale extends Solid{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); + $this->axis = Facing::axis($face); return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - public function getVariantBitmask() : int{ - return 0x03; - } - public function getFlameEncouragement() : int{ return 60; } diff --git a/src/pocketmine/block/Ice.php b/src/pocketmine/block/Ice.php index 071de1fd4..fb100a4f7 100644 --- a/src/pocketmine/block/Ice.php +++ b/src/pocketmine/block/Ice.php @@ -31,8 +31,8 @@ class Ice extends Transparent{ protected $id = self::ICE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Iron.php b/src/pocketmine/block/Iron.php index 772a8d664..0246fe536 100644 --- a/src/pocketmine/block/Iron.php +++ b/src/pocketmine/block/Iron.php @@ -29,8 +29,8 @@ class Iron extends Solid{ protected $id = self::IRON_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/IronBars.php b/src/pocketmine/block/IronBars.php index 7e6030f09..755c0d12c 100644 --- a/src/pocketmine/block/IronBars.php +++ b/src/pocketmine/block/IronBars.php @@ -29,8 +29,8 @@ class IronBars extends Thin{ protected $id = self::IRON_BARS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ @@ -48,8 +48,4 @@ class IronBars extends Thin{ public function getToolHarvestLevel() : int{ return TieredTool::TIER_WOODEN; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/IronDoor.php b/src/pocketmine/block/IronDoor.php index b097d4d26..c9da8160a 100644 --- a/src/pocketmine/block/IronDoor.php +++ b/src/pocketmine/block/IronDoor.php @@ -32,8 +32,8 @@ class IronDoor extends Door{ protected $itemId = Item::IRON_DOOR; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/IronOre.php b/src/pocketmine/block/IronOre.php index bda7572da..c41c7518e 100644 --- a/src/pocketmine/block/IronOre.php +++ b/src/pocketmine/block/IronOre.php @@ -29,8 +29,8 @@ class IronOre extends Solid{ protected $id = self::IRON_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/ItemFrame.php b/src/pocketmine/block/ItemFrame.php index 0c9f43e64..8e3315390 100644 --- a/src/pocketmine/block/ItemFrame.php +++ b/src/pocketmine/block/ItemFrame.php @@ -35,8 +35,23 @@ class ItemFrame extends Flowable{ protected $itemId = Item::ITEM_FRAME; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return 5 - $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = 5 - $meta; + } + + public function getStateBitmask() : int{ + return 0b11; } public function getName() : string{ @@ -59,7 +74,7 @@ class ItemFrame extends Flowable{ } public function onNearbyBlockChange() : void{ - if(!$this->getSide(Facing::opposite(5 - $this->meta))->isSolid()){ + if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){ $this->level->useBreakOn($this); } } @@ -69,7 +84,7 @@ class ItemFrame extends Flowable{ return false; } - $this->meta = 5 - $face; + $this->facing = $face; if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this, $face, $item, $player)); @@ -80,10 +95,6 @@ class ItemFrame extends Flowable{ } - public function getVariantBitmask() : int{ - return 0; - } - public function getDropsForCompatibleTool(Item $item) : array{ $drops = parent::getDropsForCompatibleTool($item); diff --git a/src/pocketmine/block/Ladder.php b/src/pocketmine/block/Ladder.php index 0f29bcb0c..b309fa18a 100644 --- a/src/pocketmine/block/Ladder.php +++ b/src/pocketmine/block/Ladder.php @@ -34,8 +34,23 @@ class Ladder extends Transparent{ protected $id = self::LADDER; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getName() : string{ @@ -69,13 +84,13 @@ class Ladder extends Transparent{ $minX = $minZ = 0; $maxX = $maxZ = 1; - if($this->meta === 2){ + if($this->facing === Facing::NORTH){ $minZ = 1 - $f; - }elseif($this->meta === 3){ + }elseif($this->facing === Facing::SOUTH){ $maxZ = $f; - }elseif($this->meta === 4){ + }elseif($this->facing === Facing::WEST){ $minX = 1 - $f; - }elseif($this->meta === 5){ + }elseif($this->facing === Facing::EAST){ $maxX = $f; } @@ -92,7 +107,7 @@ class Ladder extends Transparent{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if(!$blockClicked->isTransparent() and Facing::axis($face) !== Facing::AXIS_Y){ - $this->meta = $face; + $this->facing = $face; return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } @@ -100,7 +115,7 @@ class Ladder extends Transparent{ } public function onNearbyBlockChange() : void{ - if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method + if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){ //Replace with common break method $this->level->useBreakOn($this); } } @@ -108,8 +123,4 @@ class Ladder extends Transparent{ public function getToolType() : int{ return BlockToolType::TYPE_AXE; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/Lapis.php b/src/pocketmine/block/Lapis.php index 3ca5c31b1..9af975e22 100644 --- a/src/pocketmine/block/Lapis.php +++ b/src/pocketmine/block/Lapis.php @@ -29,8 +29,8 @@ class Lapis extends Solid{ protected $id = self::LAPIS_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/LapisOre.php b/src/pocketmine/block/LapisOre.php index 18bccaf98..171cf0dd4 100644 --- a/src/pocketmine/block/LapisOre.php +++ b/src/pocketmine/block/LapisOre.php @@ -31,8 +31,8 @@ class LapisOre extends Solid{ protected $id = self::LAPIS_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Lava.php b/src/pocketmine/block/Lava.php index 7757cd36d..c653c0d3a 100644 --- a/src/pocketmine/block/Lava.php +++ b/src/pocketmine/block/Lava.php @@ -35,8 +35,8 @@ class Lava extends Liquid{ protected $id = self::FLOWING_LAVA; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getLightLevel() : int{ @@ -48,11 +48,11 @@ class Lava extends Liquid{ } public function getStillForm() : Block{ - return BlockFactory::get(Block::STILL_LAVA, $this->meta); + return BlockFactory::get(Block::STILL_LAVA, $this->getDamage()); } public function getFlowingForm() : Block{ - return BlockFactory::get(Block::FLOWING_LAVA, $this->meta); + return BlockFactory::get(Block::FLOWING_LAVA, $this->getDamage()); } public function getBucketFillSound() : int{ @@ -85,19 +85,19 @@ class Lava extends Liquid{ } if($colliding !== null){ - if($this->getDamage() === 0){ + if($this->decay === 0){ $this->liquidCollide($colliding, BlockFactory::get(Block::OBSIDIAN)); - }elseif($this->getDamage() <= 4){ + }elseif($this->decay <= 4){ $this->liquidCollide($colliding, BlockFactory::get(Block::COBBLESTONE)); } } } - protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{ + protected function flowIntoBlock(Block $block, int $newFlowDecay, bool $falling) : void{ if($block instanceof Water){ $block->liquidCollide($this, BlockFactory::get(Block::STONE)); }else{ - parent::flowIntoBlock($block, $newFlowDecay); + parent::flowIntoBlock($block, $newFlowDecay, $falling); } } diff --git a/src/pocketmine/block/Leaves.php b/src/pocketmine/block/Leaves.php index 5d32a721d..11dd7fc4b 100644 --- a/src/pocketmine/block/Leaves.php +++ b/src/pocketmine/block/Leaves.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\block\utils\WoodType; use pocketmine\event\block\LeavesDecayEvent; use pocketmine\item\Item; use pocketmine\item\ItemFactory; @@ -32,17 +33,30 @@ use pocketmine\math\Vector3; use pocketmine\Player; class Leaves extends Transparent{ - public const OAK = 0; - public const SPRUCE = 1; - public const BIRCH = 2; - public const JUNGLE = 3; - public const ACACIA = 0; - public const DARK_OAK = 1; + /** @var int */ + protected $woodType; - protected $id = self::LEAVES; + /** @var bool */ + protected $noDecay = false; + /** @var bool */ + protected $checkDecay = false; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(int $id, int $variant, int $woodType, ?string $name = null){ + parent::__construct($id, $variant, $name); + $this->woodType = $woodType; + } + + protected function writeStateToMeta() : int{ + return ($this->noDecay ? 0x04 : 0) | ($this->checkDecay ? 0x08 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->noDecay = ($meta & 0x04) !== 0; + $this->checkDecay = ($meta & 0x08) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1100; } public function getHardness() : float{ @@ -53,16 +67,6 @@ class Leaves extends Transparent{ return BlockToolType::TYPE_SHEARS; } - public function getName() : string{ - static $names = [ - self::OAK => "Oak Leaves", - self::SPRUCE => "Spruce Leaves", - self::BIRCH => "Birch Leaves", - self::JUNGLE => "Jungle Leaves" - ]; - return $names[$this->getVariant()]; - } - public function diffusesSkyLight() : bool{ return true; } @@ -80,7 +84,7 @@ class Leaves extends Transparent{ return true; } - if($pos->getId() === $this->id and $distance <= 4){ + if($pos->getId() === $this->getId() and $distance <= 4){ foreach(Facing::ALL as $side){ if($this->findLog($pos->getSide($side), $visited, $distance + 1)){ return true; @@ -92,8 +96,8 @@ class Leaves extends Transparent{ } public function onNearbyBlockChange() : void{ - if(($this->meta & 0b00001100) === 0){ - $this->meta |= 0x08; + if(!$this->noDecay and !$this->checkDecay){ + $this->checkDecay = true; $this->getLevel()->setBlock($this, $this, true, false); } } @@ -103,9 +107,7 @@ class Leaves extends Transparent{ } public function onRandomTick() : void{ - if(($this->meta & 0b00001100) === 0x08){ - $this->meta &= 0x03; - + if(!$this->noDecay and $this->checkDecay){ $this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this)); if($ev->isCancelled() or $this->findLog($this)){ @@ -117,14 +119,10 @@ class Leaves extends Transparent{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - $this->meta |= 0x04; + $this->noDecay = true; //artificial leaves don't decay return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - public function getVariantBitmask() : int{ - return 0x03; - } - public function getDrops(Item $item) : array{ if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){ return $this->getDropsForCompatibleTool($item); @@ -132,23 +130,15 @@ class Leaves extends Transparent{ $drops = []; if(mt_rand(1, 20) === 1){ //Saplings - $drops[] = $this->getSaplingItem(); + $drops[] = ItemFactory::get(Item::SAPLING, $this->woodType); } - if($this->canDropApples() and mt_rand(1, 200) === 1){ //Apples + if(($this->woodType === WoodType::OAK or $this->woodType === WoodType::DARK_OAK) and mt_rand(1, 200) === 1){ //Apples $drops[] = ItemFactory::get(Item::APPLE); } return $drops; } - public function getSaplingItem() : Item{ - return ItemFactory::get(Item::SAPLING, $this->getVariant()); - } - - public function canDropApples() : bool{ - return $this->meta === self::OAK; - } - public function getFlameEncouragement() : int{ return 30; } diff --git a/src/pocketmine/block/Leaves2.php b/src/pocketmine/block/Leaves2.php deleted file mode 100644 index 3038e3319..000000000 --- a/src/pocketmine/block/Leaves2.php +++ /dev/null @@ -1,48 +0,0 @@ - "Acacia Leaves", - self::DARK_OAK => "Dark Oak Leaves" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - - public function getSaplingItem() : Item{ - return ItemFactory::get(Item::SAPLING, $this->getVariant() + 4); - } - - public function canDropApples() : bool{ - return $this->meta === self::DARK_OAK; - } -} diff --git a/src/pocketmine/block/Lever.php b/src/pocketmine/block/Lever.php index 6cd6b8480..a44ef16f2 100644 --- a/src/pocketmine/block/Lever.php +++ b/src/pocketmine/block/Lever.php @@ -30,11 +30,52 @@ use pocketmine\math\Vector3; use pocketmine\Player; class Lever extends Flowable{ + protected const BOTTOM = 0; + protected const SIDE = 1; + protected const TOP = 2; protected $id = self::LEVER; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $position = self::BOTTOM; + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $powered = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + if($this->position === self::BOTTOM){ + $rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 7 : 0; + }elseif($this->position === self::TOP){ + $rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 5 : 6; + }else{ + $rotationMeta = 6 - $this->facing; + } + return $rotationMeta | ($this->powered ? 0x08 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $rotationMeta = $meta & 0x07; + if($rotationMeta === 5 or $rotationMeta === 6){ + $this->position = self::TOP; + $this->facing = $rotationMeta === 5 ? Facing::SOUTH : Facing::EAST; + }elseif($rotationMeta === 7 or $rotationMeta === 0){ + $this->position = self::BOTTOM; + $this->facing = $rotationMeta === 7 ? Facing::SOUTH : Facing::EAST; + }else{ + $this->position = self::SIDE; + $this->facing = 6 - $rotationMeta; + } + + $this->powered = ($meta & 0x08) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ @@ -45,49 +86,34 @@ class Lever extends Flowable{ return 0.5; } - public function getVariantBitmask() : int{ - return 0; - } - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if(!$blockClicked->isSolid()){ return false; } - if($face === Facing::DOWN){ - $this->meta = 0; - }else{ - $this->meta = 6 - $face; - } - - if($player !== null){ - $bearing = $player->getDirection(); - if($bearing === Bearing::EAST or $bearing === Bearing::WEST){ - if($face === Facing::UP){ - $this->meta = 6; - } - }else{ - if($face === Facing::DOWN){ - $this->meta = 7; - } + if(Facing::axis($face) === Facing::AXIS_Y){ + if($player !== null){ + $this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection())); } + $this->position = $face === Facing::DOWN ? self::BOTTOM : self::TOP; + }else{ + $this->facing = $face; + $this->position = self::SIDE; } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } public function onNearbyBlockChange() : void{ - static $faces = [ - 0 => Facing::UP, - 1 => Facing::WEST, - 2 => Facing::EAST, - 3 => Facing::NORTH, - 4 => Facing::SOUTH, - 5 => Facing::DOWN, - 6 => Facing::DOWN, - 7 => Facing::UP - ]; - if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){ + if($this->position === self::BOTTOM){ + $face = Facing::UP; + }elseif($this->position === self::TOP){ + $face = Facing::DOWN; + }else{ + $face = Facing::opposite($this->facing); + } + + if(!$this->getSide($face)->isSolid()){ $this->level->useBreakOn($this); } } diff --git a/src/pocketmine/block/Liquid.php b/src/pocketmine/block/Liquid.php index 16cfc1633..978d3c520 100644 --- a/src/pocketmine/block/Liquid.php +++ b/src/pocketmine/block/Liquid.php @@ -44,6 +44,24 @@ abstract class Liquid extends Transparent{ private const CAN_FLOW = 0; private const BLOCKED = -1; + /** @var bool */ + protected $falling = false; + /** @var int */ + protected $decay = 0; //PC "level" property + + protected function writeStateToMeta() : int{ + return $this->decay | ($this->falling ? 0x08 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->decay = $meta & 0x07; + $this->falling = ($meta & 0x08) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; + } + public function hasEntityCollision() : bool{ return true; } @@ -84,35 +102,20 @@ abstract class Liquid extends Transparent{ abstract public function getBucketEmptySound() : int; - public function getFluidHeightPercent(){ - $d = $this->meta; - if($d >= 8){ - $d = 0; - } - - return ($d + 1) / 9; + public function isSource() : bool{ + return !$this->falling and $this->decay === 0; } - protected function getFlowDecay(Block $block) : int{ - if($block->getId() !== $this->getId()){ - return -1; - } - - return $block->getDamage(); + public function getFluidHeightPercent(){ + return (($this->falling ? 0 : $this->decay) + 1) / 9; } protected function getEffectiveFlowDecay(Block $block) : int{ - if($block->getId() !== $this->getId()){ + if(!($block instanceof Liquid) or $block->getId() !== $this->getId()){ return -1; } - $decay = $block->getDamage(); - - if($decay >= 8){ - $decay = 0; - } - - return $decay; + return $block->falling ? 0 : $block->decay; } public function clearCaches() : void{ @@ -170,7 +173,7 @@ abstract class Liquid extends Transparent{ } } - if($this->getDamage() >= 8){ + if($this->falling){ if( !$this->canFlowInto($this->level->getBlockAt($this->x, $this->y, $this->z - 1)) or !$this->canFlowInto($this->level->getBlockAt($this->x, $this->y, $this->z + 1)) or @@ -214,10 +217,9 @@ abstract class Liquid extends Transparent{ } public function onScheduledUpdate() : void{ - $decay = $this->getFlowDecay($this); $multiplier = $this->getFlowDecayPerBlock(); - if($decay > 0){ + if(!$this->isSource()){ $smallestFlowDecay = -100; $this->adjacentSources = 0; $smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay); @@ -226,80 +228,81 @@ abstract class Liquid extends Transparent{ $smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay); $newDecay = $smallestFlowDecay + $multiplier; + $falling = false; if($newDecay >= 8 or $smallestFlowDecay < 0){ $newDecay = -1; } - if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){ - $newDecay = $topFlowDecay | 0x08; + if($this->getEffectiveFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z)) >= 0){ + $falling = true; } if($this->adjacentSources >= 2 and $this instanceof Water){ $bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z); - if($bottomBlock->isSolid()){ - $newDecay = 0; - }elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){ + if($bottomBlock->isSolid() or ($bottomBlock instanceof Water and $bottomBlock->isSource())){ $newDecay = 0; + $falling = false; } } - if($newDecay !== $decay){ - $decay = $newDecay; - if($decay < 0){ + if($newDecay !== $this->decay or $falling !== $this->falling){ + if(!$falling and $newDecay < 0){ $this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true); - }else{ - $this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true); - $this->level->scheduleDelayedBlockUpdate($this, $this->tickRate()); + return; + } + + $this->falling = $falling; + $this->decay = $falling ? 0 : $newDecay; + $this->level->setBlock($this, $this, true, true); //local block update will cause an update to be scheduled + } + } + + $bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z); + + $this->flowIntoBlock($bottomBlock, 0, true); + + if($this->isSource() or !$bottomBlock->canBeFlowedInto()){ + if($this->falling){ + $adjacentDecay = 1; //falling liquid behaves like source block + }else{ + $adjacentDecay = $this->decay + $multiplier; + } + + if($adjacentDecay < 8){ + $flags = $this->getOptimalFlowDirections(); + + if($flags[0]){ + $this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay, false); + } + + if($flags[1]){ + $this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay, false); + } + + if($flags[2]){ + $this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay, false); + } + + if($flags[3]){ + $this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay, false); } } } - if($decay >= 0){ - $bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z); - - $this->flowIntoBlock($bottomBlock, $decay | 0x08); - - if($decay === 0 or !$bottomBlock->canBeFlowedInto()){ - if($decay >= 8){ - $adjacentDecay = 1; - }else{ - $adjacentDecay = $decay + $multiplier; - } - - if($adjacentDecay < 8){ - $flags = $this->getOptimalFlowDirections(); - - if($flags[0]){ - $this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay); - } - - if($flags[1]){ - $this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay); - } - - if($flags[2]){ - $this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay); - } - - if($flags[3]){ - $this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay); - } - } - } - - $this->checkForHarden(); - } + $this->checkForHarden(); } - protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{ + protected function flowIntoBlock(Block $block, int $newFlowDecay, bool $falling) : void{ if($this->canFlowInto($block) and !($block instanceof Liquid)){ if($block->getId() > 0){ $this->level->useBreakOn($block); } - $this->level->setBlock($block, BlockFactory::get($this->getId(), $newFlowDecay), true, true); - $this->level->scheduleDelayedBlockUpdate($block, $this->tickRate()); + $new = clone $this; + $new->falling = $falling; + $new->decay = $falling ? 0 : $newFlowDecay; + $this->level->setBlock($block, $new, true, true); } } @@ -407,13 +410,15 @@ abstract class Liquid extends Transparent{ } private function getSmallestFlowDecay(Block $block, int $decay) : int{ - $blockDecay = $this->getFlowDecay($block); - - if($blockDecay < 0){ + if(!($block instanceof Liquid) or $block->getId() !== $this->getId()){ return $decay; - }elseif($blockDecay === 0){ + } + + $blockDecay = $block->decay; + + if($block->isSource()){ ++$this->adjacentSources; - }elseif($blockDecay >= 8){ + }elseif($block->falling){ $blockDecay = 0; } @@ -433,6 +438,6 @@ abstract class Liquid extends Transparent{ } protected function canFlowInto(Block $block) : bool{ - return $block->canBeFlowedInto() and !($block instanceof Liquid and $block->meta === 0); //TODO: I think this should only be liquids of the same type + return $block->canBeFlowedInto() and !($block instanceof Liquid and $block->isSource()); //TODO: I think this should only be liquids of the same type } } diff --git a/src/pocketmine/block/LitRedstoneLamp.php b/src/pocketmine/block/LitRedstoneLamp.php deleted file mode 100644 index ecc8128f0..000000000 --- a/src/pocketmine/block/LitRedstoneLamp.php +++ /dev/null @@ -1,37 +0,0 @@ -setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Melon.php b/src/pocketmine/block/Melon.php index 649f839d2..c21cff0c6 100644 --- a/src/pocketmine/block/Melon.php +++ b/src/pocketmine/block/Melon.php @@ -30,8 +30,8 @@ class Melon extends Transparent{ protected $id = self::MELON_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/MelonStem.php b/src/pocketmine/block/MelonStem.php index e8763cb2d..aeb6eabc7 100644 --- a/src/pocketmine/block/MelonStem.php +++ b/src/pocketmine/block/MelonStem.php @@ -37,15 +37,11 @@ class MelonStem extends Crops{ return "Melon Stem"; } - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function onRandomTick() : void{ if(mt_rand(0, 2) === 1){ - if($this->meta < 0x07){ + if($this->age < 7){ $block = clone $this; - ++$block->meta; + ++$block->age; Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block)); if(!$ev->isCancelled()){ $this->getLevel()->setBlock($this, $ev->getNewState(), true); diff --git a/src/pocketmine/block/MonsterSpawner.php b/src/pocketmine/block/MonsterSpawner.php index 4829fd4f8..d4fc11197 100644 --- a/src/pocketmine/block/MonsterSpawner.php +++ b/src/pocketmine/block/MonsterSpawner.php @@ -30,8 +30,8 @@ class MonsterSpawner extends Transparent{ protected $id = self::MONSTER_SPAWNER; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Mycelium.php b/src/pocketmine/block/Mycelium.php index 1c5692a52..b56edf755 100644 --- a/src/pocketmine/block/Mycelium.php +++ b/src/pocketmine/block/Mycelium.php @@ -33,8 +33,8 @@ class Mycelium extends Solid{ protected $id = self::MYCELIUM; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/NetherBrickFence.php b/src/pocketmine/block/NetherBrickFence.php index 099518fd2..b8cd98afb 100644 --- a/src/pocketmine/block/NetherBrickFence.php +++ b/src/pocketmine/block/NetherBrickFence.php @@ -29,6 +29,10 @@ class NetherBrickFence extends Fence{ protected $id = self::NETHER_BRICK_FENCE; + public function __construct(){ + + } + public function getHardness() : float{ return 2; } diff --git a/src/pocketmine/block/NetherBrickStairs.php b/src/pocketmine/block/NetherBrickStairs.php index 190a66e3c..f67c87795 100644 --- a/src/pocketmine/block/NetherBrickStairs.php +++ b/src/pocketmine/block/NetherBrickStairs.php @@ -29,8 +29,8 @@ class NetherBrickStairs extends Stair{ protected $id = self::NETHER_BRICK_STAIRS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/NetherQuartzOre.php b/src/pocketmine/block/NetherQuartzOre.php index 7280203a5..7405acf63 100644 --- a/src/pocketmine/block/NetherQuartzOre.php +++ b/src/pocketmine/block/NetherQuartzOre.php @@ -31,8 +31,8 @@ class NetherQuartzOre extends Solid{ protected $id = Block::NETHER_QUARTZ_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/NetherReactor.php b/src/pocketmine/block/NetherReactor.php index fdaa0cb86..1ea1a3332 100644 --- a/src/pocketmine/block/NetherReactor.php +++ b/src/pocketmine/block/NetherReactor.php @@ -28,19 +28,33 @@ use pocketmine\item\ItemFactory; use pocketmine\item\TieredTool; class NetherReactor extends Solid{ + protected const STATE_INACTIVE = 0; + protected const STATE_ACTIVE = 1; + protected const STATE_USED = 2; + protected $id = Block::NETHER_REACTOR; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $state = self::STATE_INACTIVE; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->state; + } + + public function readStateFromMeta(int $meta) : void{ + $this->state = $meta; + } + + public function getStateBitmask() : int{ + return 0b11; } public function getName() : string{ - static $prefixes = [ - "", - "Active ", - "Used " - ]; - return ($prefixes[$this->meta] ?? "") . "Nether Reactor Core"; + return "Nether Reactor Core"; } public function getToolType() : int{ diff --git a/src/pocketmine/block/NetherWartBlock.php b/src/pocketmine/block/NetherWartBlock.php index ac960d920..21cdc6f50 100644 --- a/src/pocketmine/block/NetherWartBlock.php +++ b/src/pocketmine/block/NetherWartBlock.php @@ -27,8 +27,8 @@ class NetherWartBlock extends Solid{ protected $id = Block::NETHER_WART_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/NetherWartPlant.php b/src/pocketmine/block/NetherWartPlant.php index 50dd5dbbe..eb68dd3e7 100644 --- a/src/pocketmine/block/NetherWartPlant.php +++ b/src/pocketmine/block/NetherWartPlant.php @@ -36,8 +36,23 @@ class NetherWartPlant extends Flowable{ protected $itemId = Item::NETHER_WART; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $age = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->age; + } + + public function readStateFromMeta(int $meta) : void{ + $this->age = $meta; + } + + public function getStateBitmask() : int{ + return 0b11; } public function getName() : string{ @@ -64,9 +79,9 @@ class NetherWartPlant extends Flowable{ } public function onRandomTick() : void{ - if($this->meta < 3 and mt_rand(0, 10) === 0){ //Still growing + if($this->age < 3 and mt_rand(0, 10) === 0){ //Still growing $block = clone $this; - $block->meta++; + $block->age++; $this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block)); if(!$ev->isCancelled()){ @@ -77,7 +92,7 @@ class NetherWartPlant extends Flowable{ public function getDropsForCompatibleTool(Item $item) : array{ return [ - ItemFactory::get($this->getItemId(), 0, ($this->getDamage() === 3 ? mt_rand(2, 4) : 1)) + ItemFactory::get($this->getItemId(), 0, ($this->age === 3 ? mt_rand(2, 4) : 1)) ]; } diff --git a/src/pocketmine/block/Netherrack.php b/src/pocketmine/block/Netherrack.php index 823a6b30c..1a79ea9f9 100644 --- a/src/pocketmine/block/Netherrack.php +++ b/src/pocketmine/block/Netherrack.php @@ -29,8 +29,8 @@ class Netherrack extends Solid{ protected $id = self::NETHERRACK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/NoteBlock.php b/src/pocketmine/block/NoteBlock.php index 4dc4fe9d4..4c30cb60f 100644 --- a/src/pocketmine/block/NoteBlock.php +++ b/src/pocketmine/block/NoteBlock.php @@ -27,8 +27,8 @@ class NoteBlock extends Solid{ protected $id = self::NOTE_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Obsidian.php b/src/pocketmine/block/Obsidian.php index f37298483..ba821ec1b 100644 --- a/src/pocketmine/block/Obsidian.php +++ b/src/pocketmine/block/Obsidian.php @@ -29,8 +29,8 @@ class Obsidian extends Solid{ protected $id = self::OBSIDIAN; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/PackedIce.php b/src/pocketmine/block/PackedIce.php index d80c91839..6ca48c390 100644 --- a/src/pocketmine/block/PackedIce.php +++ b/src/pocketmine/block/PackedIce.php @@ -27,8 +27,8 @@ class PackedIce extends Solid{ protected $id = self::PACKED_ICE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Planks.php b/src/pocketmine/block/Planks.php index 9e5efe705..2acf2c071 100644 --- a/src/pocketmine/block/Planks.php +++ b/src/pocketmine/block/Planks.php @@ -24,18 +24,6 @@ declare(strict_types=1); namespace pocketmine\block; class Planks extends Solid{ - public const OAK = 0; - public const SPRUCE = 1; - public const BIRCH = 2; - public const JUNGLE = 3; - public const ACACIA = 4; - public const DARK_OAK = 5; - - protected $id = self::WOODEN_PLANKS; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } public function getHardness() : float{ return 2; @@ -45,18 +33,6 @@ class Planks extends Solid{ return BlockToolType::TYPE_AXE; } - public function getName() : string{ - static $names = [ - self::OAK => "Oak Wood Planks", - self::SPRUCE => "Spruce Wood Planks", - self::BIRCH => "Birch Wood Planks", - self::JUNGLE => "Jungle Wood Planks", - self::ACACIA => "Acacia Wood Planks", - self::DARK_OAK => "Dark Oak Wood Planks" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - public function getFuelTime() : int{ return 300; } diff --git a/src/pocketmine/block/Podzol.php b/src/pocketmine/block/Podzol.php index 470c8fabd..be44cf1b4 100644 --- a/src/pocketmine/block/Podzol.php +++ b/src/pocketmine/block/Podzol.php @@ -27,8 +27,8 @@ class Podzol extends Solid{ protected $id = self::PODZOL; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getToolType() : int{ diff --git a/src/pocketmine/block/Potato.php b/src/pocketmine/block/Potato.php index 87d0efa2d..9c00722fa 100644 --- a/src/pocketmine/block/Potato.php +++ b/src/pocketmine/block/Potato.php @@ -30,17 +30,13 @@ class Potato extends Crops{ protected $id = self::POTATO_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getName() : string{ return "Potato Block"; } public function getDropsForCompatibleTool(Item $item) : array{ return [ - ItemFactory::get(Item::POTATO, 0, $this->getDamage() >= 0x07 ? mt_rand(1, 4) : 1) + ItemFactory::get(Item::POTATO, 0, $this->age >= 7 ? mt_rand(1, 4) : 1) ]; } diff --git a/src/pocketmine/block/Prismarine.php b/src/pocketmine/block/Prismarine.php index 42a3fad71..c850bfaaf 100644 --- a/src/pocketmine/block/Prismarine.php +++ b/src/pocketmine/block/Prismarine.php @@ -31,25 +31,10 @@ class Prismarine extends Solid{ public const DARK = 1; public const BRICKS = 2; - protected $id = self::PRISMARINE; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 1.5; } - public function getName() : string{ - static $names = [ - self::NORMAL => "Prismarine", - self::DARK => "Dark Prismarine", - self::BRICKS => "Prismarine Bricks" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } @@ -57,8 +42,4 @@ class Prismarine extends Solid{ public function getToolHarvestLevel() : int{ return TieredTool::TIER_WOODEN; } - - public function getVariantBitmask() : int{ - return 0x03; - } } diff --git a/src/pocketmine/block/Pumpkin.php b/src/pocketmine/block/Pumpkin.php index 598114b1e..245996a71 100644 --- a/src/pocketmine/block/Pumpkin.php +++ b/src/pocketmine/block/Pumpkin.php @@ -27,8 +27,8 @@ class Pumpkin extends Solid{ protected $id = self::PUMPKIN; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ @@ -42,8 +42,4 @@ class Pumpkin extends Solid{ public function getName() : string{ return "Pumpkin"; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/PumpkinStem.php b/src/pocketmine/block/PumpkinStem.php index dba366297..1c916606b 100644 --- a/src/pocketmine/block/PumpkinStem.php +++ b/src/pocketmine/block/PumpkinStem.php @@ -33,19 +33,15 @@ class PumpkinStem extends Crops{ protected $id = self::PUMPKIN_STEM; - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getName() : string{ return "Pumpkin Stem"; } public function onRandomTick() : void{ if(mt_rand(0, 2) === 1){ - if($this->meta < 0x07){ + if($this->age < 7){ $block = clone $this; - ++$block->meta; + ++$block->age; Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block)); if(!$ev->isCancelled()){ $this->getLevel()->setBlock($this, $ev->getNewState(), true); diff --git a/src/pocketmine/block/Purpur.php b/src/pocketmine/block/Purpur.php index 30854b62b..a2e3c49f6 100644 --- a/src/pocketmine/block/Purpur.php +++ b/src/pocketmine/block/Purpur.php @@ -25,18 +25,6 @@ namespace pocketmine\block; class Purpur extends Quartz{ - protected $id = self::PURPUR_BLOCK; - - public function getName() : string{ - static $names = [ - self::NORMAL => "Purpur Block", - self::CHISELED => "Chiseled Purpur", //wtf? - self::PILLAR => "Purpur Pillar" - ]; - - return $names[$this->getVariant()] ?? "Unknown"; - } - public function getHardness() : float{ return 1.5; } diff --git a/src/pocketmine/block/PurpurStairs.php b/src/pocketmine/block/PurpurStairs.php index 4e21183c5..49409be4f 100644 --- a/src/pocketmine/block/PurpurStairs.php +++ b/src/pocketmine/block/PurpurStairs.php @@ -29,8 +29,8 @@ class PurpurStairs extends Stair{ protected $id = self::PURPUR_STAIRS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Quartz.php b/src/pocketmine/block/Quartz.php index 162191d9e..eb66aaff9 100644 --- a/src/pocketmine/block/Quartz.php +++ b/src/pocketmine/block/Quartz.php @@ -23,40 +23,27 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\PillarRotationHelper; +use pocketmine\block\utils\PillarRotationTrait; use pocketmine\item\Item; use pocketmine\item\TieredTool; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; class Quartz extends Solid{ + use PillarRotationTrait; public const NORMAL = 0; public const CHISELED = 1; public const PILLAR = 2; - protected $id = self::QUARTZ_BLOCK; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 0.8; } - public function getName() : string{ - static $names = [ - self::NORMAL => "Quartz Block", - self::CHISELED => "Chiseled Quartz Block", - self::PILLAR => "Quartz Pillar" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - if($this->meta !== self::NORMAL){ - $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); + if($this->variant !== self::NORMAL){ + $this->axis = Facing::axis($face); } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } @@ -68,8 +55,4 @@ class Quartz extends Solid{ public function getToolHarvestLevel() : int{ return TieredTool::TIER_WOODEN; } - - public function getVariantBitmask() : int{ - return 0x03; - } } diff --git a/src/pocketmine/block/QuartzStairs.php b/src/pocketmine/block/QuartzStairs.php index e748ca385..56b93156d 100644 --- a/src/pocketmine/block/QuartzStairs.php +++ b/src/pocketmine/block/QuartzStairs.php @@ -29,8 +29,8 @@ class QuartzStairs extends Stair{ protected $id = self::QUARTZ_STAIRS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Rail.php b/src/pocketmine/block/Rail.php index 643e61ff0..b7d5ab8a9 100644 --- a/src/pocketmine/block/Rail.php +++ b/src/pocketmine/block/Rail.php @@ -66,8 +66,8 @@ class Rail extends BaseRail{ } } - protected function getConnectionsForState() : array{ - return self::CURVE_CONNECTIONS[$this->meta] ?? self::CONNECTIONS[$this->meta]; + protected function getConnectionsFromMeta(int $meta) : array{ + return self::CURVE_CONNECTIONS[$meta] ?? self::CONNECTIONS[$meta] ?? []; } protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{ diff --git a/src/pocketmine/block/RedMushroom.php b/src/pocketmine/block/RedMushroom.php index 1ed607697..be4d6e1bb 100644 --- a/src/pocketmine/block/RedMushroom.php +++ b/src/pocketmine/block/RedMushroom.php @@ -32,8 +32,8 @@ class RedMushroom extends Flowable{ protected $id = self::RED_MUSHROOM; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/RedMushroomBlock.php b/src/pocketmine/block/RedMushroomBlock.php index f89213867..3281b8d46 100644 --- a/src/pocketmine/block/RedMushroomBlock.php +++ b/src/pocketmine/block/RedMushroomBlock.php @@ -29,8 +29,29 @@ class RedMushroomBlock extends Solid{ protected $id = Block::RED_MUSHROOM_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** + * @var int + * In PC they have blockstate properties for each of the sides (pores/not pores). Unfortunately, we can't support + * that because we can't serialize 2^6 combinations into a 4-bit metadata value, so this has to stick with storing + * the legacy crap for now. + * TODO: change this once proper blockstates are implemented + */ + protected $rotationData = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->rotationData; + } + + public function readStateFromMeta(int $meta) : void{ + $this->rotationData = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ diff --git a/src/pocketmine/block/RedSandstone.php b/src/pocketmine/block/RedSandstone.php deleted file mode 100644 index 8c2372ccc..000000000 --- a/src/pocketmine/block/RedSandstone.php +++ /dev/null @@ -1,37 +0,0 @@ - "Red Sandstone", - self::CHISELED => "Chiseled Red Sandstone", - self::SMOOTH => "Smooth Red Sandstone" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } -} diff --git a/src/pocketmine/block/Redstone.php b/src/pocketmine/block/Redstone.php index 7430138c9..f88c571a0 100644 --- a/src/pocketmine/block/Redstone.php +++ b/src/pocketmine/block/Redstone.php @@ -29,8 +29,8 @@ class Redstone extends Solid{ protected $id = self::REDSTONE_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/RedstoneLamp.php b/src/pocketmine/block/RedstoneLamp.php index 8a33c6e94..421268d7e 100644 --- a/src/pocketmine/block/RedstoneLamp.php +++ b/src/pocketmine/block/RedstoneLamp.php @@ -25,10 +25,29 @@ namespace pocketmine\block; class RedstoneLamp extends Solid{ - protected $id = self::REDSTONE_LAMP; + protected $itemId = self::REDSTONE_LAMP; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $lit = false; + + public function __construct(){ + + } + + public function getId() : int{ + return $this->lit ? self::LIT_REDSTONE_LAMP : self::REDSTONE_LAMP; + } + + public function isLit() : bool{ + return $this->lit; + } + + public function setLit(bool $lit = true) : void{ + $this->lit = $lit; + } + + public function getLightLevel() : int{ + return $this->lit ? 15 : 0; } public function getName() : string{ diff --git a/src/pocketmine/block/RedstoneOre.php b/src/pocketmine/block/RedstoneOre.php index b0900799e..495634a3b 100644 --- a/src/pocketmine/block/RedstoneOre.php +++ b/src/pocketmine/block/RedstoneOre.php @@ -31,10 +31,17 @@ use pocketmine\Player; class RedstoneOre extends Solid{ - protected $id = self::REDSTONE_ORE; + protected $itemId = self::REDSTONE_ORE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $lit = false; + + public function __construct(){ + + } + + public function getId() : int{ + return $this->lit ? self::GLOWING_REDSTONE_ORE : self::REDSTONE_ORE; } public function getName() : string{ @@ -45,17 +52,46 @@ class RedstoneOre extends Solid{ return 3; } + public function isLit() : bool{ + return $this->lit; + } + + public function setLit(bool $lit = true) : void{ + $this->lit = $lit; + } + + public function getLightLevel() : int{ + return $this->lit ? 9 : 0; + } + public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ return $this->getLevel()->setBlock($this, $this, true, false); } public function onActivate(Item $item, Player $player = null) : bool{ - $this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta)); - return false; //this shouldn't prevent block placement + if(!$this->lit){ + $this->lit = true; + $this->getLevel()->setBlock($this, $this); //no return here - this shouldn't prevent block placement + } + return false; } public function onNearbyBlockChange() : void{ - $this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta)); + if(!$this->lit){ + $this->lit = true; + $this->getLevel()->setBlock($this, $this); + } + } + + public function ticksRandomly() : bool{ + return true; + } + + public function onRandomTick() : void{ + if($this->lit){ + $this->lit = false; + $this->level->setBlock($this, $this); + } } public function getToolType() : int{ diff --git a/src/pocketmine/block/RedstoneRail.php b/src/pocketmine/block/RedstoneRail.php index 7d3b9cd4c..a02f11635 100644 --- a/src/pocketmine/block/RedstoneRail.php +++ b/src/pocketmine/block/RedstoneRail.php @@ -26,7 +26,23 @@ namespace pocketmine\block; class RedstoneRail extends BaseRail{ protected const FLAG_POWERED = 0x08; - protected function getConnectionsForState() : array{ - return self::CONNECTIONS[$this->meta & ~self::FLAG_POWERED]; + /** @var bool */ + protected $powered = false; + + protected function writeStateToMeta() : int{ + return parent::writeStateToMeta() | ($this->powered ? self::FLAG_POWERED : 0); + } + + public function readStateFromMeta(int $meta) : void{ + parent::readStateFromMeta($meta); + $this->powered = ($meta & self::FLAG_POWERED) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; + } + + protected function getConnectionsFromMeta(int $meta) : array{ + return self::CONNECTIONS[$meta & ~self::FLAG_POWERED] ?? []; } } diff --git a/src/pocketmine/block/RedstoneTorch.php b/src/pocketmine/block/RedstoneTorch.php index 4d0770d1d..c8b9ab9a5 100644 --- a/src/pocketmine/block/RedstoneTorch.php +++ b/src/pocketmine/block/RedstoneTorch.php @@ -25,13 +25,28 @@ namespace pocketmine\block; class RedstoneTorch extends Torch{ - protected $id = self::LIT_REDSTONE_TORCH; + protected $itemId = self::REDSTONE_TORCH; + + /** @var bool */ + protected $lit = true; + + public function getId() : int{ + return $this->lit ? self::REDSTONE_TORCH : self::UNLIT_REDSTONE_TORCH; + } public function getName() : string{ return "Redstone Torch"; } + public function isLit() : bool{ + return $this->lit; + } + + public function setLit(bool $lit = true) : void{ + $this->lit = $lit; + } + public function getLightLevel() : int{ - return 7; + return $this->lit ? 7 : 0; } } diff --git a/src/pocketmine/block/RedstoneTorchUnlit.php b/src/pocketmine/block/RedstoneTorchUnlit.php deleted file mode 100644 index f074d0f66..000000000 --- a/src/pocketmine/block/RedstoneTorchUnlit.php +++ /dev/null @@ -1,37 +0,0 @@ -setDamage($meta); - } - public function getHardness() : float{ return 0.5; } @@ -38,12 +32,4 @@ class Sand extends Fallable{ public function getToolType() : int{ return BlockToolType::TYPE_SHOVEL; } - - public function getName() : string{ - if($this->meta === 0x01){ - return "Red Sand"; - } - - return "Sand"; - } } diff --git a/src/pocketmine/block/Sandstone.php b/src/pocketmine/block/Sandstone.php index d7b829801..17571564a 100644 --- a/src/pocketmine/block/Sandstone.php +++ b/src/pocketmine/block/Sandstone.php @@ -31,25 +31,10 @@ class Sandstone extends Solid{ public const CHISELED = 1; public const SMOOTH = 2; - protected $id = self::SANDSTONE; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 0.8; } - public function getName() : string{ - static $names = [ - self::NORMAL => "Sandstone", - self::CHISELED => "Chiseled Sandstone", - self::SMOOTH => "Smooth Sandstone" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } @@ -57,8 +42,4 @@ class Sandstone extends Solid{ public function getToolHarvestLevel() : int{ return TieredTool::TIER_WOODEN; } - - public function getVariantBitmask() : int{ - return 0x03; - } } diff --git a/src/pocketmine/block/SandstoneStairs.php b/src/pocketmine/block/SandstoneStairs.php index 4bdc87b7f..aeeb0152e 100644 --- a/src/pocketmine/block/SandstoneStairs.php +++ b/src/pocketmine/block/SandstoneStairs.php @@ -29,8 +29,8 @@ class SandstoneStairs extends Stair{ protected $id = self::SANDSTONE_STAIRS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/Sapling.php b/src/pocketmine/block/Sapling.php index 8c9db99e9..3ec18bf9f 100644 --- a/src/pocketmine/block/Sapling.php +++ b/src/pocketmine/block/Sapling.php @@ -31,29 +31,20 @@ use pocketmine\Player; use pocketmine\utils\Random; class Sapling extends Flowable{ - public const OAK = 0; - public const SPRUCE = 1; - public const BIRCH = 2; - public const JUNGLE = 3; - public const ACACIA = 4; - public const DARK_OAK = 5; - protected $id = self::SAPLING; + /** @var bool */ + protected $ready = false; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + protected function writeStateToMeta() : int{ + return ($this->ready ? 0x08 : 0); } - public function getName() : string{ - static $names = [ - 0 => "Oak Sapling", - 1 => "Spruce Sapling", - 2 => "Birch Sapling", - 3 => "Jungle Sapling", - 4 => "Acacia Sapling", - 5 => "Dark Oak Sapling" - ]; - return $names[$this->getVariant()] ?? "Unknown"; + public function readStateFromMeta(int $meta) : void{ + $this->ready = ($meta & 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{ @@ -90,19 +81,15 @@ class Sapling extends Flowable{ public function onRandomTick() : void{ if($this->level->getFullLightAt($this->x, $this->y, $this->z) >= 8 and mt_rand(1, 7) === 1){ - if(($this->meta & 0x08) === 0x08){ + if($this->ready){ Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant()); }else{ - $this->meta |= 0x08; + $this->ready = true; $this->getLevel()->setBlock($this, $this, true); } } } - public function getVariantBitmask() : int{ - return 0x07; - } - public function getFuelTime() : int{ return 100; } diff --git a/src/pocketmine/block/SeaLantern.php b/src/pocketmine/block/SeaLantern.php index 5fcaa87f0..3d0e3009f 100644 --- a/src/pocketmine/block/SeaLantern.php +++ b/src/pocketmine/block/SeaLantern.php @@ -30,8 +30,8 @@ class SeaLantern extends Transparent{ protected $id = self::SEA_LANTERN; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/SignPost.php b/src/pocketmine/block/SignPost.php index 87e47aea7..b37ec9e84 100644 --- a/src/pocketmine/block/SignPost.php +++ b/src/pocketmine/block/SignPost.php @@ -37,8 +37,23 @@ class SignPost extends Transparent{ protected $itemId = Item::SIGN; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $rotation = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->rotation; + } + + public function readStateFromMeta(int $meta) : void{ + $this->rotation = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getHardness() : float{ @@ -57,16 +72,14 @@ class SignPost extends Transparent{ return null; } - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if($face !== Facing::DOWN){ if($face === Facing::UP){ - $this->meta = $player !== null ? (floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0f) : 0; + $this->rotation = $player !== null ? ((int) floor((($player->yaw + 180) * 16 / 360) + 0.5)) & 0x0f : 0; $ret = parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); }else{ - $this->meta = $face; - $ret = $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_SIGN, $this->meta), true); + $ret = $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_SIGN, $face), true); } if($ret){ @@ -87,8 +100,4 @@ class SignPost extends Transparent{ public function getToolType() : int{ return BlockToolType::TYPE_AXE; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/Skull.php b/src/pocketmine/block/Skull.php index bdfaef4a1..8eb9677e9 100644 --- a/src/pocketmine/block/Skull.php +++ b/src/pocketmine/block/Skull.php @@ -36,8 +36,23 @@ class Skull extends Flowable{ protected $id = self::SKULL_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getHardness() : float{ @@ -49,7 +64,7 @@ class Skull extends Flowable{ } protected function recalculateBoundingBox() : ?AxisAlignedBB{ - //TODO: different bounds depending on attached face (meta) + //TODO: different bounds depending on attached face static $f = 0.25; return new AxisAlignedBB($f, 0, $f, 1 - $f, 0.5, 1 - $f); } @@ -59,7 +74,7 @@ class Skull extends Flowable{ return false; } - $this->meta = $face; + $this->facing = $face; if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ Tile::createTile(Tile::SKULL, $this->getLevel(), TileSkull::createNBT($this, $face, $item, $player)); return true; diff --git a/src/pocketmine/block/Slab.php b/src/pocketmine/block/Slab.php index 26ea65ca3..abe6561fc 100644 --- a/src/pocketmine/block/Slab.php +++ b/src/pocketmine/block/Slab.php @@ -30,20 +30,40 @@ use pocketmine\math\Vector3; use pocketmine\Player; abstract class Slab extends Transparent{ + /** @var int */ + protected $doubleId; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $top = false; + + public function __construct(int $id, int $doubleId, int $variant = 0, ?string $name = null){ + parent::__construct($id, $variant, $name . " Slab"); + $this->doubleId = $doubleId; } - abstract public function getDoubleSlabId() : int; + protected function writeStateToMeta() : int{ + return ($this->top ? 0x08 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->top = ($meta & 0x08) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1000; + } + + public function getDoubleSlabId() : int{ + return $this->doubleId; + } public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{ if(parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock)){ return true; } - if($blockReplace->getId() === $this->getId() and $blockReplace->getVariant() === $this->getVariant()){ - if(($blockReplace->getDamage() & 0x08) !== 0){ //Trying to combine with top slab + if($blockReplace instanceof Slab and $blockReplace->getId() === $this->getId() and $blockReplace->getVariant() === $this->variant){ + if($blockReplace->top){ //Trying to combine with top slab return $clickVector->y <= 0.5 or (!$isClickedBlock and $face === Facing::UP); }else{ return $clickVector->y >= 0.5 or (!$isClickedBlock and $face === Facing::DOWN); @@ -54,33 +74,32 @@ abstract class Slab extends Transparent{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - $this->meta &= 0x07; if($face === Facing::DOWN){ - if($blockClicked->getId() === $this->id and ($blockClicked->getDamage() & 0x08) === 0x08 and $blockClicked->getVariant() === $this->getVariant()){ - $this->getLevel()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); + if($blockClicked instanceof Slab and $blockClicked->getId() === $this->getId() and $blockClicked->top and $blockClicked->getVariant() === $this->variant){ + $this->getLevel()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->variant), true); return true; - }elseif($blockReplace->getId() === $this->id and $blockReplace->getVariant() === $this->getVariant()){ - $this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); + }elseif($blockReplace->getId() === $this->getId() and $blockReplace->getVariant() === $this->variant){ + $this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->variant), true); return true; }else{ - $this->meta |= 0x08; + $this->top = true; } }elseif($face === Facing::UP){ - if($blockClicked->getId() === $this->id and ($blockClicked->getDamage() & 0x08) === 0 and $blockClicked->getVariant() === $this->getVariant()){ - $this->getLevel()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); + if($blockClicked instanceof Slab and $blockClicked->getId() === $this->getId() and !$blockClicked->top and $blockClicked->getVariant() === $this->variant){ + $this->getLevel()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->variant), true); return true; - }elseif($blockReplace->getId() === $this->id and $blockReplace->getVariant() === $this->getVariant()){ - $this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); + }elseif($blockReplace->getId() === $this->getId() and $blockReplace->getVariant() === $this->variant){ + $this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->variant), true); return true; } }else{ //TODO: collision - if($blockReplace->getId() === $this->id){ - if($blockReplace->getVariant() === $this->meta){ - $this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); + if($blockReplace->getId() === $this->getId()){ + if($blockReplace->getVariant() === $this->variant){ + $this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->variant), true); return true; } @@ -88,25 +107,20 @@ abstract class Slab extends Transparent{ return false; }else{ if($clickVector->y > 0.5){ - $this->meta |= 0x08; + $this->top = true; } } } - if($blockReplace->getId() === $this->id and $blockClicked->getVariant() !== $this->getVariant()){ + if($blockReplace->getId() === $this->getId() and $blockClicked->getVariant() !== $this->variant){ return false; } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - public function getVariantBitmask() : int{ - return 0x07; - } - protected function recalculateBoundingBox() : ?AxisAlignedBB{ - - if(($this->meta & 0x08) > 0){ + if($this->top){ return new AxisAlignedBB(0, 0.5, 0, 1, 1, 1); }else{ return new AxisAlignedBB(0, 0, 0, 1, 0.5, 1); diff --git a/src/pocketmine/block/Snow.php b/src/pocketmine/block/Snow.php index 20e9919c1..707a72af2 100644 --- a/src/pocketmine/block/Snow.php +++ b/src/pocketmine/block/Snow.php @@ -31,8 +31,8 @@ class Snow extends Solid{ protected $id = self::SNOW_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getHardness() : float{ diff --git a/src/pocketmine/block/SnowLayer.php b/src/pocketmine/block/SnowLayer.php index 0a709d45b..faa73bab1 100644 --- a/src/pocketmine/block/SnowLayer.php +++ b/src/pocketmine/block/SnowLayer.php @@ -34,8 +34,23 @@ class SnowLayer extends Flowable{ protected $id = self::SNOW_LAYER; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $layers = 1; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->layers - 1; + } + + public function readStateFromMeta(int $meta) : void{ + $this->layers = $meta + 1; + } + + public function getStateBitmask() : int{ + return 0b111; } public function getName() : string{ diff --git a/src/pocketmine/block/SoulSand.php b/src/pocketmine/block/SoulSand.php index 44e9900fd..9df0ac22b 100644 --- a/src/pocketmine/block/SoulSand.php +++ b/src/pocketmine/block/SoulSand.php @@ -29,8 +29,8 @@ class SoulSand extends Solid{ protected $id = self::SOUL_SAND; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Sponge.php b/src/pocketmine/block/Sponge.php index 1f9289e20..d84c352f6 100644 --- a/src/pocketmine/block/Sponge.php +++ b/src/pocketmine/block/Sponge.php @@ -28,8 +28,23 @@ class Sponge extends Solid{ protected $id = self::SPONGE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $wet = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->wet ? 1 : 0; + } + + public function readStateFromMeta(int $meta) : void{ + $this->wet = $meta !== 0; + } + + public function getStateBitmask() : int{ + return 0b1; } public function getHardness() : float{ diff --git a/src/pocketmine/block/StainedClay.php b/src/pocketmine/block/StainedClay.php deleted file mode 100644 index 3807dab66..000000000 --- a/src/pocketmine/block/StainedClay.php +++ /dev/null @@ -1,35 +0,0 @@ -meta) . " Stained Clay"; - } -} diff --git a/src/pocketmine/block/StainedGlass.php b/src/pocketmine/block/StainedGlass.php deleted file mode 100644 index 76aa65d2d..000000000 --- a/src/pocketmine/block/StainedGlass.php +++ /dev/null @@ -1,35 +0,0 @@ -meta) . " Stained Glass"; - } -} diff --git a/src/pocketmine/block/StainedGlassPane.php b/src/pocketmine/block/StainedGlassPane.php deleted file mode 100644 index 01a9d35df..000000000 --- a/src/pocketmine/block/StainedGlassPane.php +++ /dev/null @@ -1,35 +0,0 @@ -meta) . " Stained Glass Pane"; - } -} diff --git a/src/pocketmine/block/Stair.php b/src/pocketmine/block/Stair.php index 1026b2fd3..23bc45240 100644 --- a/src/pocketmine/block/Stair.php +++ b/src/pocketmine/block/Stair.php @@ -31,57 +31,64 @@ use pocketmine\math\Vector3; use pocketmine\Player; abstract class Stair extends Transparent{ + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $upsideDown = false; + + protected function writeStateToMeta() : int{ + return (5 - $this->facing) | ($this->upsideDown ? 0x04 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = 5 - ($meta & 0x03); + $this->upsideDown = ($meta & 0x04) !== 0; + } + + public function getStateBitmask() : int{ + return 0b111; + } protected function recalculateCollisionBoxes() : array{ //TODO: handle corners - $minYSlab = ($this->meta & 0x04) === 0 ? 0 : 0.5; - $maxYSlab = $minYSlab + 0.5; + $minYSlab = $this->upsideDown ? 0.5 : 0; $bbs = [ - new AxisAlignedBB(0, $minYSlab, 0, 1, $maxYSlab, 1) + new AxisAlignedBB(0, $minYSlab, 0, 1, $minYSlab + 0.5, 1) ]; - $minY = ($this->meta & 0x04) === 0 ? 0.5 : 0; - $maxY = $minY + 0.5; - - $rotationMeta = $this->meta & 0x03; + $minY = $this->upsideDown ? 0 : 0.5; $minX = $minZ = 0; $maxX = $maxZ = 1; - switch($rotationMeta){ - case 0: + switch($this->facing){ + case Facing::EAST: $minX = 0.5; break; - case 1: + case Facing::WEST: $maxX = 0.5; break; - case 2: + case Facing::SOUTH: $minZ = 0.5; break; - case 3: + case Facing::NORTH: $maxZ = 0.5; break; } - $bbs[] = new AxisAlignedBB($minX, $minY, $minZ, $maxX, $maxY, $maxZ); + $bbs[] = new AxisAlignedBB($minX, $minY, $minZ, $maxX, $minY + 0.5, $maxZ); return $bbs; } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if($player !== null){ - $this->meta = 5 - Bearing::toFacing($player->getDirection()); - } - if(($clickVector->y > 0.5 and $face !== Facing::UP) or $face === Facing::DOWN){ - $this->meta |= 0x04; //Upside-down stairs + $this->facing = Bearing::toFacing($player->getDirection()); } + $this->upsideDown = (($clickVector->y > 0.5 and $face !== Facing::UP) or $face === Facing::DOWN); return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/StandingBanner.php b/src/pocketmine/block/StandingBanner.php index 388ae5e6d..5dc4b43da 100644 --- a/src/pocketmine/block/StandingBanner.php +++ b/src/pocketmine/block/StandingBanner.php @@ -38,8 +38,23 @@ class StandingBanner extends Transparent{ protected $itemId = Item::BANNER; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $rotation = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->rotation; + } + + public function readStateFromMeta(int $meta) : void{ + $this->rotation = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getHardness() : float{ @@ -61,11 +76,10 @@ class StandingBanner extends Transparent{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if($face !== Facing::DOWN){ if($face === Facing::UP and $player !== null){ - $this->meta = floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0f; + $this->rotation = ((int) floor((($player->yaw + 180) * 16 / 360) + 0.5)) & 0x0f; $ret = parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); }else{ - $this->meta = $face; - $ret = $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_BANNER, $this->meta), true); + $ret = $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_BANNER, $face), true); } if($ret){ @@ -87,10 +101,6 @@ class StandingBanner extends Transparent{ return BlockToolType::TYPE_AXE; } - public function getVariantBitmask() : int{ - return 0; - } - public function getDropsForCompatibleTool(Item $item) : array{ $tile = $this->level->getTile($this); diff --git a/src/pocketmine/block/Stone.php b/src/pocketmine/block/Stone.php index 47b096235..0878abec3 100644 --- a/src/pocketmine/block/Stone.php +++ b/src/pocketmine/block/Stone.php @@ -36,12 +36,6 @@ class Stone extends Solid{ public const ANDESITE = 5; public const POLISHED_ANDESITE = 6; - protected $id = self::STONE; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 1.5; } @@ -54,23 +48,10 @@ class Stone extends Solid{ return TieredTool::TIER_WOODEN; } - public function getName() : string{ - static $names = [ - self::NORMAL => "Stone", - self::GRANITE => "Granite", - self::POLISHED_GRANITE => "Polished Granite", - self::DIORITE => "Diorite", - self::POLISHED_DIORITE => "Polished Diorite", - self::ANDESITE => "Andesite", - self::POLISHED_ANDESITE => "Polished Andesite" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - public function getDropsForCompatibleTool(Item $item) : array{ - if($this->getDamage() === self::NORMAL){ + if($this->variant === self::NORMAL){ return [ - ItemFactory::get(Item::COBBLESTONE, $this->getDamage()) + ItemFactory::get(Item::COBBLESTONE) ]; } diff --git a/src/pocketmine/block/StoneBrickStairs.php b/src/pocketmine/block/StoneBrickStairs.php index ec397251a..c0cb53059 100644 --- a/src/pocketmine/block/StoneBrickStairs.php +++ b/src/pocketmine/block/StoneBrickStairs.php @@ -29,8 +29,8 @@ class StoneBrickStairs extends Stair{ protected $id = self::STONE_BRICK_STAIRS; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getToolType() : int{ diff --git a/src/pocketmine/block/StoneBricks.php b/src/pocketmine/block/StoneBricks.php index 34518a823..fca2d9937 100644 --- a/src/pocketmine/block/StoneBricks.php +++ b/src/pocketmine/block/StoneBricks.php @@ -31,12 +31,6 @@ class StoneBricks extends Solid{ public const CRACKED = 2; public const CHISELED = 3; - protected $id = self::STONE_BRICKS; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 1.5; } @@ -48,14 +42,4 @@ class StoneBricks extends Solid{ public function getToolHarvestLevel() : int{ return TieredTool::TIER_WOODEN; } - - public function getName() : string{ - static $names = [ - self::NORMAL => "Stone Bricks", - self::MOSSY => "Mossy Stone Bricks", - self::CRACKED => "Cracked Stone Bricks", - self::CHISELED => "Chiseled Stone Bricks" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } } diff --git a/src/pocketmine/block/StonePressurePlate.php b/src/pocketmine/block/StonePressurePlate.php index f11f7aebc..027d10ae3 100644 --- a/src/pocketmine/block/StonePressurePlate.php +++ b/src/pocketmine/block/StonePressurePlate.php @@ -29,8 +29,23 @@ class StonePressurePlate extends Transparent{ protected $id = self::STONE_PRESSURE_PLATE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $powered = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->powered ? 1 : 0; + } + + public function readStateFromMeta(int $meta) : void{ + $this->powered = $meta !== 0; + } + + public function getStateBitmask() : int{ + return 0b1; } public function getName() : string{ @@ -45,10 +60,6 @@ class StonePressurePlate extends Transparent{ return 0.5; } - public function getVariantBitmask() : int{ - return 0; - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } diff --git a/src/pocketmine/block/StoneSlab.php b/src/pocketmine/block/StoneSlab.php index 19d3dbe5c..56ae176d9 100644 --- a/src/pocketmine/block/StoneSlab.php +++ b/src/pocketmine/block/StoneSlab.php @@ -26,39 +26,11 @@ namespace pocketmine\block; use pocketmine\item\TieredTool; class StoneSlab extends Slab{ - public const STONE = 0; - public const SANDSTONE = 1; - public const WOODEN = 2; - public const COBBLESTONE = 3; - public const BRICK = 4; - public const STONE_BRICK = 5; - public const QUARTZ = 6; - public const NETHER_BRICK = 7; - - protected $id = self::STONE_SLAB; - - public function getDoubleSlabId() : int{ - return self::DOUBLE_STONE_SLAB; - } public function getHardness() : float{ return 2; } - public function getName() : string{ - static $names = [ - self::STONE => "Stone", - self::SANDSTONE => "Sandstone", - self::WOODEN => "Wooden", - self::COBBLESTONE => "Cobblestone", - self::BRICK => "Brick", - self::STONE_BRICK => "Stone Brick", - self::QUARTZ => "Quartz", - self::NETHER_BRICK => "Nether Brick" - ]; - return (($this->meta & 0x08) > 0 ? "Upper " : "") . ($names[$this->getVariant()] ?? "") . " Slab"; - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } diff --git a/src/pocketmine/block/StoneSlab2.php b/src/pocketmine/block/StoneSlab2.php deleted file mode 100644 index 1f3a9c44e..000000000 --- a/src/pocketmine/block/StoneSlab2.php +++ /dev/null @@ -1,44 +0,0 @@ - "Red Sandstone", - self::TYPE_PURPUR => "Purpur" - ]; - - return (($this->meta & 0x08) > 0 ? "Upper " : "") . ($names[$this->getVariant()] ?? "") . " Slab"; - } -} diff --git a/src/pocketmine/block/Stonecutter.php b/src/pocketmine/block/Stonecutter.php index 1532b2338..daaf02d85 100644 --- a/src/pocketmine/block/Stonecutter.php +++ b/src/pocketmine/block/Stonecutter.php @@ -29,8 +29,8 @@ class Stonecutter extends Solid{ protected $id = self::STONECUTTER; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/Sugarcane.php b/src/pocketmine/block/Sugarcane.php index f3e25880c..70381022a 100644 --- a/src/pocketmine/block/Sugarcane.php +++ b/src/pocketmine/block/Sugarcane.php @@ -36,8 +36,23 @@ class Sugarcane extends Flowable{ protected $itemId = Item::SUGARCANE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $age = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->age; + } + + public function readStateFromMeta(int $meta) : void{ + $this->age = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ @@ -57,7 +72,7 @@ class Sugarcane extends Flowable{ break; } } - $this->meta = 0; + $this->age = 0; $this->getLevel()->setBlock($this, $this, true); } @@ -82,7 +97,7 @@ class Sugarcane extends Flowable{ public function onRandomTick() : void{ if($this->getSide(Facing::DOWN)->getId() !== self::SUGARCANE_BLOCK){ - if($this->meta === 0x0F){ + if($this->age === 15){ for($y = 1; $y < 3; ++$y){ $b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z); if($b->getId() === self::AIR){ @@ -90,10 +105,10 @@ class Sugarcane extends Flowable{ break; } } - $this->meta = 0; + $this->age = 0; $this->getLevel()->setBlock($this, $this, true); }else{ - ++$this->meta; + ++$this->age; $this->getLevel()->setBlock($this, $this, true); } } @@ -113,8 +128,4 @@ class Sugarcane extends Flowable{ return false; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/TNT.php b/src/pocketmine/block/TNT.php index 7fa63d9d0..2a13c18af 100644 --- a/src/pocketmine/block/TNT.php +++ b/src/pocketmine/block/TNT.php @@ -35,8 +35,8 @@ class TNT extends Solid{ protected $id = self::TNT; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ diff --git a/src/pocketmine/block/TallGrass.php b/src/pocketmine/block/TallGrass.php index d7e0b45f5..f439a2204 100644 --- a/src/pocketmine/block/TallGrass.php +++ b/src/pocketmine/block/TallGrass.php @@ -31,25 +31,10 @@ use pocketmine\Player; class TallGrass extends Flowable{ - protected $id = self::TALL_GRASS; - - public function __construct(int $meta = 1){ - $this->setDamage($meta); - } - public function canBeReplaced() : bool{ return true; } - public function getName() : string{ - static $names = [ - 0 => "Dead Shrub", - 1 => "Tall Grass", - 2 => "Fern" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - 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){ diff --git a/src/pocketmine/block/Torch.php b/src/pocketmine/block/Torch.php index a4269ac6a..6524faa55 100644 --- a/src/pocketmine/block/Torch.php +++ b/src/pocketmine/block/Torch.php @@ -32,8 +32,27 @@ class Torch extends Flowable{ protected $id = self::TORCH; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::UP; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->facing === Facing::DOWN ? 0 : 6 - $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + if($meta === 0){ + $this->facing = Facing::DOWN; + }else{ + $this->facing = 6 - $meta; + } + } + + public function getStateBitmask() : int{ + return 0b111; } public function getLightLevel() : int{ @@ -46,7 +65,7 @@ class Torch extends Flowable{ public function onNearbyBlockChange() : void{ $below = $this->getSide(Facing::DOWN); - $face = $this->meta === 0 ? Facing::DOWN : Facing::opposite(6 - $this->meta); + $face = Facing::opposite($this->facing); if($this->getSide($face)->isTransparent() and !($face === Facing::DOWN and ($below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL))){ $this->getLevel()->useBreakOn($this); @@ -57,18 +76,13 @@ class Torch extends Flowable{ $below = $this->getSide(Facing::DOWN); if(!$blockClicked->isTransparent() and $face !== Facing::DOWN){ - $this->meta = 6 - $face; - + $this->facing = $face; return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); }elseif(!$below->isTransparent() or $below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL){ - $this->meta = 5; //attached to block below + $this->facing = Facing::UP; return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } return false; } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/Trapdoor.php b/src/pocketmine/block/Trapdoor.php index 0b5278582..641f82e96 100644 --- a/src/pocketmine/block/Trapdoor.php +++ b/src/pocketmine/block/Trapdoor.php @@ -42,8 +42,31 @@ class Trapdoor extends Transparent{ protected $id = self::TRAPDOOR; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $open = false; + /** @var bool */ + protected $top = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return (5 - $this->facing) | ($this->top ? self::MASK_UPPER : 0) | ($this->open ? self::MASK_OPENED : 0); + } + + public function readStateFromMeta(int $meta) : void{ + //TODO: in PC the values are reversed (3 - (5 - facing)) + + $this->facing = 5 - ($meta & 0x03); + $this->top = ($meta & self::MASK_UPPER) !== 0; + $this->open = ($meta & self::MASK_OPENED) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ @@ -55,26 +78,22 @@ class Trapdoor extends Transparent{ } protected function recalculateBoundingBox() : ?AxisAlignedBB{ - - $damage = $this->getDamage(); - $f = 0.1875; - if(($damage & self::MASK_UPPER) > 0){ + if($this->top){ $bb = new AxisAlignedBB(0, 1 - $f, 0, 1, 1, 1); }else{ $bb = new AxisAlignedBB(0, 0, 0, 1, $f, 1); } - if(($damage & self::MASK_OPENED) > 0){ - $side = $damage & 0x03; - if($side === self::MASK_SIDE_NORTH){ + if($this->open){ + if($this->facing === Facing::NORTH){ $bb->setBounds(0, 0, 1 - $f, 1, 1, 1); - }elseif($side === self::MASK_SIDE_SOUTH){ + }elseif($this->facing === Facing::SOUTH){ $bb->setBounds(0, 0, 0, 1, 1, $f); - }elseif($side === self::MASK_SIDE_WEST){ + }elseif($this->facing === Facing::WEST){ $bb->setBounds(1 - $f, 0, 0, 1, 1, 1); - }elseif($side === self::MASK_SIDE_EAST){ + }elseif($this->facing === Facing::EAST){ $bb->setBounds(0, 0, 0, $f, 1, 1); } } @@ -84,23 +103,18 @@ class Trapdoor extends Transparent{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ if($player !== null){ - //TODO: in PC the values are reversed (3 - (5 - facing)) - $this->meta = 5 - Bearing::toFacing(Bearing::opposite($player->getDirection())); + $this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection())); } if(($clickVector->y > 0.5 and $face !== Facing::UP) or $face === Facing::DOWN){ - $this->meta |= self::MASK_UPPER; //top half of block + $this->top = true; } return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - public function getVariantBitmask() : int{ - return 0; - } - public function onActivate(Item $item, Player $player = null) : bool{ - $this->meta ^= self::MASK_OPENED; - $this->getLevel()->setBlock($this, $this, true); + $this->open = !$this->open; + $this->level->setBlock($this, $this, true); $this->level->addSound(new DoorSound($this)); return true; } diff --git a/src/pocketmine/block/Tripwire.php b/src/pocketmine/block/Tripwire.php index e916fcb69..397a5f40d 100644 --- a/src/pocketmine/block/Tripwire.php +++ b/src/pocketmine/block/Tripwire.php @@ -30,8 +30,29 @@ class Tripwire extends Flowable{ protected $id = self::TRIPWIRE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool */ + protected $triggered = false; + /** @var bool */ + protected $connected = false; + /** @var bool */ + protected $disarmed = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return ($this->triggered ? 0x01 : 0) | ($this->connected ? 0x04 : 0) | ($this->disarmed ? 0x08 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->triggered = ($meta & 0x01) !== 0; + $this->connected = ($meta & 0x04) !== 0; + $this->disarmed = ($meta & 0x08) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ diff --git a/src/pocketmine/block/TripwireHook.php b/src/pocketmine/block/TripwireHook.php index f505dd92a..ef56ce847 100644 --- a/src/pocketmine/block/TripwireHook.php +++ b/src/pocketmine/block/TripwireHook.php @@ -23,20 +23,52 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\item\Item; +use pocketmine\math\Bearing; +use pocketmine\math\Facing; +use pocketmine\math\Vector3; +use pocketmine\Player; + class TripwireHook extends Flowable{ protected $id = self::TRIPWIRE_HOOK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $facing = Facing::NORTH; + /** @var bool */ + protected $connected = false; + /** @var bool */ + protected $powered = false; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return Bearing::fromFacing($this->facing) | ($this->connected ? 0x04 : 0) | ($this->powered ? 0x08 : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = Bearing::toFacing($meta & 0x03); + $this->connected = ($meta & 0x04) !== 0; + $this->powered = ($meta & 0x08) !== 0; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ return "Tripwire Hook"; } - public function getVariantBitmask() : int{ - return 0; + 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 + $this->facing = $face; + return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); + } + return false; } //TODO diff --git a/src/pocketmine/block/UnknownBlock.php b/src/pocketmine/block/UnknownBlock.php index e12420710..37ea74af9 100644 --- a/src/pocketmine/block/UnknownBlock.php +++ b/src/pocketmine/block/UnknownBlock.php @@ -27,6 +27,15 @@ use pocketmine\item\Item; class UnknownBlock extends Transparent{ + public function __construct(int $id, int $meta = 0){ + $this->id = $id; + $this->variant = $meta; + } + + public function canBePlaced() : bool{ + return false; + } + public function getHardness() : float{ return 0; } diff --git a/src/pocketmine/block/Vine.php b/src/pocketmine/block/Vine.php index 300c120b2..1f0061157 100644 --- a/src/pocketmine/block/Vine.php +++ b/src/pocketmine/block/Vine.php @@ -38,8 +38,36 @@ class Vine extends Flowable{ protected $id = self::VINE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var bool[] */ + protected $faces = []; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return + (isset($this->faces[Facing::SOUTH]) ? self::FLAG_SOUTH : 0) | + (isset($this->faces[Facing::WEST]) ? self::FLAG_WEST : 0) | + (isset($this->faces[Facing::NORTH]) ? self::FLAG_NORTH : 0) | + (isset($this->faces[Facing::EAST]) ? self::FLAG_EAST : 0); + } + + public function readStateFromMeta(int $meta) : void{ + $this->setFaceFromMeta($meta, self::FLAG_SOUTH, Facing::SOUTH); + $this->setFaceFromMeta($meta, self::FLAG_WEST, Facing::WEST); + $this->setFaceFromMeta($meta, self::FLAG_NORTH, Facing::NORTH); + $this->setFaceFromMeta($meta, 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; + } } public function getName() : string{ @@ -79,7 +107,7 @@ class Vine extends Flowable{ $minY = 0; $hasSide = false; - if(($this->meta & self::FLAG_WEST) > 0){ + if(isset($this->faces[Facing::WEST])){ $maxX = max($maxX, 0.0625); $minX = 0; $minZ = 0; @@ -87,7 +115,7 @@ class Vine extends Flowable{ $hasSide = true; } - if(($this->meta & self::FLAG_EAST) > 0){ + if(isset($this->faces[Facing::EAST])){ $minX = min($minX, 0.9375); $maxX = 1; $minZ = 0; @@ -95,7 +123,7 @@ class Vine extends Flowable{ $hasSide = true; } - if(($this->meta & self::FLAG_SOUTH) > 0){ + if(isset($this->faces[Facing::SOUTH])){ $minZ = min($minZ, 0.9375); $maxZ = 1; $minX = 0; @@ -103,7 +131,7 @@ class Vine extends Flowable{ $hasSide = true; } - if(($this->meta & self::FLAG_NORTH) > 0){ + if(isset($this->faces[Facing::NORTH])){ $maxZ = max($maxZ, 0.0625); $minZ = 0; $minX = 0; @@ -123,50 +151,29 @@ class Vine extends Flowable{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - if(!$blockClicked->isSolid() or $face === Facing::UP or $face === Facing::DOWN){ + if(!$blockClicked->isSolid() or Facing::axis($face) === Facing::AXIS_Y){ return false; } - static $faces = [ - Facing::NORTH => self::FLAG_SOUTH, - Facing::SOUTH => self::FLAG_NORTH, - Facing::WEST => self::FLAG_EAST, - Facing::EAST => self::FLAG_WEST - ]; - - $this->meta = $faces[$face] ?? 0; - if($blockReplace->getId() === $this->getId()){ - $this->meta |= $blockReplace->meta; - } + $this->faces = $blockReplace instanceof Vine ? $blockReplace->faces : []; + $this->faces[Facing::opposite($face)] = true; return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } public function onNearbyBlockChange() : void{ - static $sides = [ - self::FLAG_SOUTH => Facing::SOUTH, - self::FLAG_WEST => Facing::WEST, - self::FLAG_NORTH => Facing::NORTH, - self::FLAG_EAST => Facing::EAST - ]; - - $meta = $this->meta; - - foreach($sides as $flag => $side){ - if(($meta & $flag) === 0){ - continue; - } - - if(!$this->getSide($side)->isSolid()){ - $meta &= ~$flag; + $changed = false; + foreach($this->faces as $face => $bool){ + if(!$this->getSide($face)->isSolid()){ + unset($this->faces[$face]); + $changed = true; } } - if($meta !== $this->meta){ - if($meta === 0){ + if($changed){ + if(empty($this->faces)){ $this->level->useBreakOn($this); }else{ - $this->meta = $meta; $this->level->setBlock($this, $this); } } @@ -180,10 +187,6 @@ class Vine extends Flowable{ //TODO: vine growth } - public function getVariantBitmask() : int{ - return 0; - } - public function getDrops(Item $item) : array{ if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){ return $this->getDropsForCompatibleTool($item); diff --git a/src/pocketmine/block/WallBanner.php b/src/pocketmine/block/WallBanner.php index a0a16ea44..a161ce847 100644 --- a/src/pocketmine/block/WallBanner.php +++ b/src/pocketmine/block/WallBanner.php @@ -23,16 +23,33 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\math\Facing; + class WallBanner extends StandingBanner{ protected $id = self::WALL_BANNER; + /** @var int */ + protected $facing = Facing::NORTH; + + protected function writeStateToMeta() : int{ + return $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; + } + public function getName() : string{ return "Wall Banner"; } public function onNearbyBlockChange() : void{ - if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){ + 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 58b0d8a82..e416e27eb 100644 --- a/src/pocketmine/block/WallSign.php +++ b/src/pocketmine/block/WallSign.php @@ -23,16 +23,33 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\math\Facing; + class WallSign extends SignPost{ protected $id = self::WALL_SIGN; + /** @var int */ + protected $facing = Facing::NORTH; + + protected function writeStateToMeta() : int{ + return $this->facing; + } + + public function readStateFromMeta(int $meta) : void{ + $this->facing = $meta; + } + + public function getStateBitmask() : int{ + return 0b111; + } + public function getName() : string{ return "Wall Sign"; } public function onNearbyBlockChange() : void{ - if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){ + if($this->getSide(Facing::opposite($this->facing))->getId() === self::AIR){ $this->getLevel()->useBreakOn($this); } } diff --git a/src/pocketmine/block/Water.php b/src/pocketmine/block/Water.php index 777696ff3..2256f202c 100644 --- a/src/pocketmine/block/Water.php +++ b/src/pocketmine/block/Water.php @@ -30,8 +30,8 @@ class Water extends Liquid{ protected $id = self::FLOWING_WATER; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ @@ -43,11 +43,11 @@ class Water extends Liquid{ } public function getStillForm() : Block{ - return BlockFactory::get(Block::STILL_WATER, $this->meta); + return BlockFactory::get(Block::STILL_WATER, $this->getDamage()); } public function getFlowingForm() : Block{ - return BlockFactory::get(Block::FLOWING_WATER, $this->meta); + return BlockFactory::get(Block::FLOWING_WATER, $this->getDamage()); } public function getBucketFillSound() : int{ diff --git a/src/pocketmine/block/WaterLily.php b/src/pocketmine/block/WaterLily.php index bd372c4f3..faf1316fa 100644 --- a/src/pocketmine/block/WaterLily.php +++ b/src/pocketmine/block/WaterLily.php @@ -33,8 +33,8 @@ class WaterLily extends Flowable{ protected $id = self::WATER_LILY; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + public function __construct(){ + } public function getName() : string{ @@ -66,8 +66,4 @@ class WaterLily extends Flowable{ $this->getLevel()->useBreakOn($this); } } - - public function getVariantBitmask() : int{ - return 0; - } } diff --git a/src/pocketmine/block/WeightedPressurePlateLight.php b/src/pocketmine/block/WeightedPressurePlateLight.php index 5633173c8..baea3a0bf 100644 --- a/src/pocketmine/block/WeightedPressurePlateLight.php +++ b/src/pocketmine/block/WeightedPressurePlateLight.php @@ -29,8 +29,23 @@ class WeightedPressurePlateLight extends Transparent{ protected $id = self::LIGHT_WEIGHTED_PRESSURE_PLATE; - public function __construct(int $meta = 0){ - $this->setDamage($meta); + /** @var int */ + protected $power = 0; + + public function __construct(){ + + } + + protected function writeStateToMeta() : int{ + return $this->power; + } + + public function readStateFromMeta(int $meta) : void{ + $this->power = $meta; + } + + public function getStateBitmask() : int{ + return 0b1111; } public function getName() : string{ @@ -45,10 +60,6 @@ class WeightedPressurePlateLight extends Transparent{ return 0.5; } - public function getVariantBitmask() : int{ - return 0; - } - public function getToolType() : int{ return BlockToolType::TYPE_PICKAXE; } diff --git a/src/pocketmine/block/Wheat.php b/src/pocketmine/block/Wheat.php index c0d455a08..ac3f0775b 100644 --- a/src/pocketmine/block/Wheat.php +++ b/src/pocketmine/block/Wheat.php @@ -30,16 +30,12 @@ class Wheat extends Crops{ protected $id = self::WHEAT_BLOCK; - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getName() : string{ return "Wheat Block"; } public function getDropsForCompatibleTool(Item $item) : array{ - if($this->meta >= 0x07){ + if($this->age >= 7){ return [ ItemFactory::get(Item::WHEAT), ItemFactory::get(Item::WHEAT_SEEDS, 0, mt_rand(0, 3)) diff --git a/src/pocketmine/block/Wood.php b/src/pocketmine/block/Wood.php index 375cd15df..9f66ef318 100644 --- a/src/pocketmine/block/Wood.php +++ b/src/pocketmine/block/Wood.php @@ -23,46 +23,29 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\PillarRotationHelper; +use pocketmine\block\utils\PillarRotationTrait; use pocketmine\item\Item; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; class Wood extends Solid{ + use PillarRotationTrait; + public const OAK = 0; public const SPRUCE = 1; public const BIRCH = 2; public const JUNGLE = 3; - protected $id = self::WOOD; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 2; } - public function getName() : string{ - static $names = [ - self::OAK => "Oak Wood", - self::SPRUCE => "Spruce Wood", - self::BIRCH => "Birch Wood", - self::JUNGLE => "Jungle Wood" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); + $this->axis = Facing::axis($face); return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - public function getVariantBitmask() : int{ - return 0x03; - } - public function getToolType() : int{ return BlockToolType::TYPE_AXE; } diff --git a/src/pocketmine/block/Wood2.php b/src/pocketmine/block/Wood2.php deleted file mode 100644 index f452aaef8..000000000 --- a/src/pocketmine/block/Wood2.php +++ /dev/null @@ -1,41 +0,0 @@ - "Acacia Wood", - 1 => "Dark Oak Wood" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } -} diff --git a/src/pocketmine/block/WoodenFence.php b/src/pocketmine/block/WoodenFence.php index f0df471f6..3190e9d87 100644 --- a/src/pocketmine/block/WoodenFence.php +++ b/src/pocketmine/block/WoodenFence.php @@ -24,14 +24,6 @@ declare(strict_types=1); namespace pocketmine\block; class WoodenFence extends Fence{ - public const FENCE_OAK = 0; - public const FENCE_SPRUCE = 1; - public const FENCE_BIRCH = 2; - public const FENCE_JUNGLE = 3; - public const FENCE_ACACIA = 4; - public const FENCE_DARKOAK = 5; - - protected $id = self::FENCE; public function getHardness() : float{ return 2; @@ -41,18 +33,6 @@ class WoodenFence extends Fence{ return BlockToolType::TYPE_AXE; } - public function getName() : string{ - static $names = [ - self::FENCE_OAK => "Oak Fence", - self::FENCE_SPRUCE => "Spruce Fence", - self::FENCE_BIRCH => "Birch Fence", - self::FENCE_JUNGLE => "Jungle Fence", - self::FENCE_ACACIA => "Acacia Fence", - self::FENCE_DARKOAK => "Dark Oak Fence" - ]; - return $names[$this->getVariant()] ?? "Unknown"; - } - public function getFuelTime() : int{ return 300; } diff --git a/src/pocketmine/block/WoodenSlab.php b/src/pocketmine/block/WoodenSlab.php index f1b8f4611..36528d695 100644 --- a/src/pocketmine/block/WoodenSlab.php +++ b/src/pocketmine/block/WoodenSlab.php @@ -23,30 +23,20 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\block\utils\WoodType; + class WoodenSlab extends Slab{ protected $id = self::WOODEN_SLAB; - public function getDoubleSlabId() : int{ - return self::DOUBLE_WOODEN_SLAB; + public function __construct(int $variant = 0){ + parent::__construct(self::WOODEN_SLAB, self::DOUBLE_WOODEN_SLAB, $variant, WoodType::NAMES[$variant]); } public function getHardness() : float{ return 2; } - public function getName() : string{ - static $names = [ - 0 => "Oak", - 1 => "Spruce", - 2 => "Birch", - 3 => "Jungle", - 4 => "Acacia", - 5 => "Dark Oak" - ]; - return (($this->meta & 0x08) === 0x08 ? "Upper " : "") . ($names[$this->getVariant()] ?? "") . " Wooden Slab"; - } - public function getToolType() : int{ return BlockToolType::TYPE_AXE; } diff --git a/src/pocketmine/block/Wool.php b/src/pocketmine/block/Wool.php index 7963a13f9..0a7b107f5 100644 --- a/src/pocketmine/block/Wool.php +++ b/src/pocketmine/block/Wool.php @@ -23,17 +23,10 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\block\utils\ColorBlockMetaHelper; use pocketmine\item\Item; class Wool extends Solid{ - protected $id = self::WOOL; - - public function __construct(int $meta = 0){ - $this->setDamage($meta); - } - public function getHardness() : float{ return 0.8; } @@ -42,10 +35,6 @@ class Wool extends Solid{ return BlockToolType::TYPE_SHEARS; } - public function getName() : string{ - return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Wool"; - } - public function getBreakTime(Item $item) : float{ $time = parent::getBreakTime($item); if($item->getBlockToolType() === BlockToolType::TYPE_SHEARS){ diff --git a/src/pocketmine/block/utils/ColorBlockMetaHelper.php b/src/pocketmine/block/utils/ColorBlockMetaHelper.php deleted file mode 100644 index 6fe8bf15e..000000000 --- a/src/pocketmine/block/utils/ColorBlockMetaHelper.php +++ /dev/null @@ -1,50 +0,0 @@ - "White", - 1 => "Orange", - 2 => "Magenta", - 3 => "Light Blue", - 4 => "Yellow", - 5 => "Lime", - 6 => "Pink", - 7 => "Gray", - 8 => "Light Gray", - 9 => "Cyan", - 10 => "Purple", - 11 => "Blue", - 12 => "Brown", - 13 => "Green", - 14 => "Red", - 15 => "Black" - ]; - - return $names[$meta] ?? "Unknown"; - } -} diff --git a/src/pocketmine/block/utils/PillarRotationHelper.php b/src/pocketmine/block/utils/PillarRotationHelper.php deleted file mode 100644 index 8e64afd92..000000000 --- a/src/pocketmine/block/utils/PillarRotationHelper.php +++ /dev/null @@ -1,39 +0,0 @@ - 0, - Facing::AXIS_Z => 0x08, - Facing::AXIS_X => 0x04 - ]; - - return ($meta & 0x03) | $bits[Facing::axis($face)]; - } -} diff --git a/src/pocketmine/item/Bucket.php b/src/pocketmine/item/Bucket.php index ce9365d82..133ccbb37 100644 --- a/src/pocketmine/item/Bucket.php +++ b/src/pocketmine/item/Bucket.php @@ -54,7 +54,7 @@ class Bucket extends Item implements Consumable{ $resultBlock = BlockFactory::get($this->meta); if($resultBlock instanceof Air){ - if($blockClicked instanceof Liquid and $blockClicked->getDamage() === 0){ + if($blockClicked instanceof Liquid and $blockClicked->isSource()){ $stack = clone $this; $stack->pop(); diff --git a/src/pocketmine/item/Dye.php b/src/pocketmine/item/Dye.php index 9443e900d..87aaa184c 100644 --- a/src/pocketmine/item/Dye.php +++ b/src/pocketmine/item/Dye.php @@ -23,10 +23,20 @@ declare(strict_types=1); namespace pocketmine\item; +use pocketmine\block\Block; +use pocketmine\block\BlockFactory; + class Dye extends Item{ public function __construct(int $meta = 0){ parent::__construct(self::DYE, $meta, "Dye"); } + public function getBlock() : Block{ + if($this->meta === 3){ //cocoa beans + return BlockFactory::get(Block::COCOA); + } + return parent::getBlock(); + } + //TODO: names } diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 14e7add6c..79068d5f0 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -216,9 +216,6 @@ class Level implements ChunkManager, Metadatable{ /** @var Vector3 */ private $temporalVector; - /** @var \SplFixedArray */ - private $blockStates; - /** @var int */ private $sleepTicks = 0; @@ -230,7 +227,7 @@ class Level implements ChunkManager, Metadatable{ private $chunksPerTick; /** @var bool */ private $clearChunksOnTick; - /** @var \SplFixedArray */ + /** @var \SplFixedArray */ private $randomTickBlocks = null; /** @var LevelTimings */ @@ -327,7 +324,6 @@ class Level implements ChunkManager, Metadatable{ * @param LevelProvider $provider */ public function __construct(Server $server, string $name, LevelProvider $provider){ - $this->blockStates = BlockFactory::getBlockStatesArray(); $this->levelId = static::$levelIdCounter++; $this->blockMetadata = new BlockMetadataStore($this); $this->server = $server; @@ -357,11 +353,17 @@ class Level implements ChunkManager, Metadatable{ $dontTickBlocks = array_fill_keys($this->server->getProperty("chunk-ticking.disable-block-ticking", []), true); - $this->randomTickBlocks = new \SplFixedArray(256); - foreach($this->randomTickBlocks as $id => $null){ - $block = BlockFactory::get($id); //Make sure it's a copy + $this->randomTickBlocks = new \SplFixedArray(4096); + foreach($this->randomTickBlocks as $i => $null){ + $id = $i >> 4; + $meta = $i & 0xf; + try{ + $block = BlockFactory::get($id, $meta); //Make sure it's a copy + }catch(\InvalidArgumentException $e){ + continue; + } if(!isset($dontTickBlocks[$id]) and $block->ticksRandomly()){ - $this->randomTickBlocks[$id] = $block; + $this->randomTickBlocks[($id << 4) | $meta] = true; } } @@ -939,12 +941,16 @@ class Level implements ChunkManager, Metadatable{ return $this->randomTickBlocks; } - public function addRandomTickedBlock(int $id){ - $this->randomTickBlocks[$id] = BlockFactory::get($id); + public function addRandomTickedBlock(int $id, int $variant = 0){ + $block = BlockFactory::get($id, $variant); + if($block instanceof UnknownBlock){ + throw new \InvalidArgumentException("ID $id variant $variant is unknown, cannot do random-tick"); + } + $this->randomTickBlocks[($id << 4) | $variant] = true; } - public function removeRandomTickedBlock(int $id){ - $this->randomTickBlocks[$id] = null; + public function removeRandomTickedBlock(int $id, int $variant = 0){ + $this->randomTickBlocks[($id << 4) | $variant] = null; } private function tickChunks(){ @@ -998,10 +1004,11 @@ class Level implements ChunkManager, Metadatable{ $z = ($k >> 8) & 0x0f; $blockId = $subChunk->getBlockId($x, $y, $z); - if($this->randomTickBlocks[$blockId] !== null){ + $meta = $subChunk->getBlockData($x, $y, $z); + + if($this->randomTickBlocks[($blockId << 4) | ($meta & ~BlockFactory::$stateMasks[$blockId])]){ /** @var Block $block */ - $block = clone $this->randomTickBlocks[$blockId]; - $block->setDamage($subChunk->getBlockData($x, $y, $z)); + $block = BlockFactory::get($blockId, $meta); $block->x = $chunkX * 16 + $x; $block->y = ($Y << 4) + $y; @@ -1335,7 +1342,8 @@ class Level implements ChunkManager, Metadatable{ * @return Block */ public function getBlockAt(int $x, int $y, int $z, bool $cached = true, bool $addToCache = true) : Block{ - $fullState = 0; + $id = 0; + $meta = 0; $blockHash = null; $chunkHash = Level::chunkHash($x >> 4, $z >> 4); @@ -1349,17 +1357,14 @@ class Level implements ChunkManager, Metadatable{ $chunk = $this->chunks[$chunkHash] ?? null; if($chunk !== null){ $fullState = $chunk->getFullBlock($x & 0x0f, $y, $z & 0x0f); + $id = $fullState >> 4; + $meta = $fullState & 0xf; }else{ $addToCache = false; } } - $block = $this->blockStates[$fullState & 0xfff]; - if($block !== null){ - $block = clone $block; - }else{ - $block = new UnknownBlock($fullState >> 4, $fullState & 0xf); - } + $block = BlockFactory::get($id, $meta); $block->x = $x; $block->y = $y; diff --git a/src/pocketmine/level/biome/ForestBiome.php b/src/pocketmine/level/biome/ForestBiome.php index 30ec1475f..0c4699c40 100644 --- a/src/pocketmine/level/biome/ForestBiome.php +++ b/src/pocketmine/level/biome/ForestBiome.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace pocketmine\level\biome; -use pocketmine\block\Sapling; +use pocketmine\block\utils\WoodType; use pocketmine\level\generator\populator\TallGrass; use pocketmine\level\generator\populator\Tree; @@ -39,7 +39,7 @@ class ForestBiome extends GrassyBiome{ $this->type = $type; - $trees = new Tree($type === self::TYPE_BIRCH ? Sapling::BIRCH : Sapling::OAK); + $trees = new Tree($type === self::TYPE_BIRCH ? WoodType::BIRCH : WoodType::OAK); $trees->setBaseAmount(5); $this->addPopulator($trees); diff --git a/src/pocketmine/level/biome/TaigaBiome.php b/src/pocketmine/level/biome/TaigaBiome.php index 90ac60b61..2404c5936 100644 --- a/src/pocketmine/level/biome/TaigaBiome.php +++ b/src/pocketmine/level/biome/TaigaBiome.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace pocketmine\level\biome; -use pocketmine\block\Sapling; +use pocketmine\block\utils\WoodType; use pocketmine\level\generator\populator\TallGrass; use pocketmine\level\generator\populator\Tree; @@ -32,7 +32,7 @@ class TaigaBiome extends SnowyBiome{ public function __construct(){ parent::__construct(); - $trees = new Tree(Sapling::SPRUCE); + $trees = new Tree(WoodType::SPRUCE); $trees->setBaseAmount(10); $this->addPopulator($trees); diff --git a/src/pocketmine/level/generator/object/Tree.php b/src/pocketmine/level/generator/object/Tree.php index f25bcf4bc..5b9110f9e 100644 --- a/src/pocketmine/level/generator/object/Tree.php +++ b/src/pocketmine/level/generator/object/Tree.php @@ -25,7 +25,7 @@ namespace pocketmine\level\generator\object; use pocketmine\block\Block; use pocketmine\block\BlockFactory; -use pocketmine\block\Sapling; +use pocketmine\block\utils\WoodType; use pocketmine\level\ChunkManager; use pocketmine\utils\Random; @@ -45,23 +45,23 @@ abstract class Tree{ public $leafBlock = Block::LEAVES; public $treeHeight = 7; - public static function growTree(ChunkManager $level, int $x, int $y, int $z, Random $random, int $type = Sapling::OAK) : void{ + public static function growTree(ChunkManager $level, int $x, int $y, int $z, Random $random, int $type = WoodType::OAK) : void{ switch($type){ - case Sapling::SPRUCE: + case WoodType::SPRUCE: $tree = new SpruceTree(); break; - case Sapling::BIRCH: + case WoodType::BIRCH: if($random->nextBoundedInt(39) === 0){ $tree = new BirchTree(true); }else{ $tree = new BirchTree(); } break; - case Sapling::JUNGLE: + case WoodType::JUNGLE: $tree = new JungleTree(); break; - case Sapling::ACACIA: - case Sapling::DARK_OAK: + case WoodType::ACACIA: + case WoodType::DARK_OAK: return; //TODO default: $tree = new OakTree(); diff --git a/src/pocketmine/level/generator/populator/Tree.php b/src/pocketmine/level/generator/populator/Tree.php index 6250aa41a..d63b311ea 100644 --- a/src/pocketmine/level/generator/populator/Tree.php +++ b/src/pocketmine/level/generator/populator/Tree.php @@ -24,7 +24,7 @@ declare(strict_types=1); namespace pocketmine\level\generator\populator; use pocketmine\block\Block; -use pocketmine\block\Sapling; +use pocketmine\block\utils\WoodType; use pocketmine\level\ChunkManager; use pocketmine\level\generator\object\Tree as ObjectTree; use pocketmine\utils\Random; @@ -37,7 +37,7 @@ class Tree extends Populator{ private $type; - public function __construct(int $type = Sapling::OAK){ + public function __construct(int $type = WoodType::OAK){ $this->type = $type; } diff --git a/src/pocketmine/tile/Furnace.php b/src/pocketmine/tile/Furnace.php index 848d5fba2..2e4dbe79e 100644 --- a/src/pocketmine/tile/Furnace.php +++ b/src/pocketmine/tile/Furnace.php @@ -23,8 +23,7 @@ declare(strict_types=1); namespace pocketmine\tile; -use pocketmine\block\Block; -use pocketmine\block\BlockFactory; +use pocketmine\block\Furnace as BlockFurnace; use pocketmine\event\inventory\FurnaceBurnEvent; use pocketmine\event\inventory\FurnaceSmeltEvent; use pocketmine\inventory\FurnaceInventory; @@ -144,8 +143,10 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ $this->maxTime = $this->burnTime = $ev->getBurnTime(); - if($this->getBlock()->getId() === Block::FURNACE){ - $this->getLevel()->setBlock($this, BlockFactory::get(Block::BURNING_FURNACE, $this->getBlock()->getDamage()), true); + $block = $this->getBlock(); + if($block instanceof BlockFurnace and !$block->isLit()){ + $block->setLit(true); + $this->getLevel()->setBlock($block, $block, true); } if($this->burnTime > 0 and $ev->isBurning()){ @@ -206,8 +207,10 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ } $ret = true; }else{ - if($this->getBlock()->getId() === Block::BURNING_FURNACE){ - $this->getLevel()->setBlock($this, BlockFactory::get(Block::FURNACE, $this->getBlock()->getDamage()), true); + $block = $this->getBlock(); + if($block instanceof BlockFurnace and $block->isLit()){ + $block->setLit(false); + $this->getLevel()->setBlock($block, $block, true); } $this->burnTime = $this->cookTime = $this->maxTime = 0; } diff --git a/tests/phpunit/block/BlockTest.php b/tests/phpunit/block/BlockTest.php index 222a4cc6c..2fae84449 100644 --- a/tests/phpunit/block/BlockTest.php +++ b/tests/phpunit/block/BlockTest.php @@ -99,11 +99,12 @@ class BlockTest extends TestCase{ */ public function blockGetProvider() : array{ return [ - [Block::STONE, Stone::ANDESITE], + [Block::STONE, 5], [Block::STONE, 15], - [Block::GOLD_BLOCK, 5], - [Block::WOODEN_PLANKS, Planks::DARK_OAK], - [Block::SAND, 0] + [Block::GOLD_BLOCK, 0], + [Block::WOODEN_PLANKS, 5], + [Block::SAND, 0], + [Block::GOLD_BLOCK, 0] ]; } @@ -119,6 +120,13 @@ class BlockTest extends TestCase{ self::assertEquals($meta, $block->getDamage()); } + public function testBlockIds() : void{ + for($i = 0; $i < 256; ++$i){ + $b = BlockFactory::get($i); + self::assertEquals($i, $b->getId()); + } + } + /** * Test that all blocks have correctly set names */