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 */