diff --git a/src/pocketmine/block/Bed.php b/src/pocketmine/block/Bed.php index a4040d95c..1672346cb 100644 --- a/src/pocketmine/block/Bed.php +++ b/src/pocketmine/block/Bed.php @@ -35,7 +35,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\Bed as TileBed; -use pocketmine\tile\TileFactory; use pocketmine\utils\TextFormat; class Bed extends Transparent{ @@ -84,13 +83,17 @@ class Bed extends Transparent{ } } + protected function getTileClass() : ?string{ + return TileBed::class; + } + public function writeStateToWorld() : void{ parent::writeStateToWorld(); //extra block properties storage hack - /** @var TileBed $tile */ - $tile = TileFactory::create(TileBed::class, $this->getLevel(), $this->asVector3()); - $tile->setColor($this->color); - $this->level->addTile($tile); + $tile = $this->level->getTile($this); + if($tile instanceof TileBed){ + $tile->setColor($this->color); + } } public function getHardness() : float{ diff --git a/src/pocketmine/block/Block.php b/src/pocketmine/block/Block.php index 1f5a23514..681d16e9d 100644 --- a/src/pocketmine/block/Block.php +++ b/src/pocketmine/block/Block.php @@ -41,6 +41,7 @@ use pocketmine\metadata\Metadatable; use pocketmine\metadata\MetadataValue; use pocketmine\Player; use pocketmine\plugin\Plugin; +use pocketmine\tile\TileFactory; use function array_merge; use function assert; use function dechex; @@ -172,8 +173,26 @@ class Block extends Position implements BlockIds, Metadatable{ $this->collisionBoxes = null; } + /** + * Returns the class of Tile associated with this block. + * + * @return string|null class extending Tile, or null + */ + protected function getTileClass() : ?string{ + return null; + } + public function writeStateToWorld() : void{ $this->level->getChunkAtPosition($this)->setBlock($this->x & 0xf, $this->y, $this->z & 0xf, $this->getId(), $this->getDamage()); + + $tileType = $this->getTileClass(); + $oldTile = $this->level->getTile($this); + if($oldTile !== null and ($tileType === null or !($oldTile instanceof $tileType))){ + $oldTile->close(); + } + if($tileType !== null){ + $this->level->addTile(TileFactory::create($tileType, $this->level, $this->asVector3())); + } } /** @@ -315,6 +334,9 @@ class Block extends Position implements BlockIds, Metadatable{ * @return bool */ public function onBreak(Item $item, Player $player = null) : bool{ + if(($t = $this->level->getTile($this)) !== null){ + $t->onBlockDestroyed(); + } return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR)); } diff --git a/src/pocketmine/block/Chest.php b/src/pocketmine/block/Chest.php index a7bdc9750..24736b3db 100644 --- a/src/pocketmine/block/Chest.php +++ b/src/pocketmine/block/Chest.php @@ -30,7 +30,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\Chest as TileChest; -use pocketmine\tile\TileFactory; class Chest extends Transparent{ @@ -55,6 +54,10 @@ class Chest extends Transparent{ return 0b111; } + protected function getTileClass() : ?string{ + return TileChest::class; + } + public function getHardness() : float{ return 2.5; } @@ -73,34 +76,28 @@ class Chest extends Transparent{ } public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - /** @var TileChest|null $pair */ - $pair = null; if($player !== null){ $this->facing = Facing::opposite($player->getHorizontalFacing()); } - foreach([ - Facing::rotateY($player->getHorizontalFacing(), false), - Facing::rotateY($player->getHorizontalFacing(), true) - ] as $side){ - $c = $this->getSide($side); - if($c instanceof Chest and $c->isSameType($this) and $c->facing === $this->facing){ - $tile = $this->getLevel()->getTile($c); - if($tile instanceof TileChest and !$tile->isPaired()){ - $pair = $tile; - break; - } - } - } - if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - /** @var TileChest $tile */ - $tile = TileFactory::createFromItem(TileChest::class, $this->getLevel(), $this->asVector3(), $item); - $this->level->addTile($tile); - - if($pair instanceof TileChest){ - $pair->pairWith($tile); - $tile->pairWith($pair); + //TODO: this is fragile and might have unintended side effects on ender chests if modified carelessly + $tile = $this->level->getTile($this); + if($tile instanceof TileChest){ + foreach([ + Facing::rotateY($this->facing, true), + Facing::rotateY($this->facing, false) + ] as $side){ + $c = $this->getSide($side); + if($c instanceof Chest and $c->isSameType($this) and $c->facing === $this->facing){ + $pair = $this->level->getTile($c); + if($pair instanceof TileChest and !$pair->isPaired()){ + $pair->pairWith($tile); + $tile->pairWith($pair); + break; + } + } + } } return true; diff --git a/src/pocketmine/block/EnchantingTable.php b/src/pocketmine/block/EnchantingTable.php index 5a1a62863..30db64abe 100644 --- a/src/pocketmine/block/EnchantingTable.php +++ b/src/pocketmine/block/EnchantingTable.php @@ -28,10 +28,8 @@ use pocketmine\item\Item; use pocketmine\item\TieredTool; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; -use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\EnchantTable as TileEnchantingTable; -use pocketmine\tile\TileFactory; class EnchantingTable extends Transparent{ @@ -41,13 +39,8 @@ class EnchantingTable extends Transparent{ } - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - $this->level->addTile(TileFactory::createFromItem(TileEnchantingTable::class, $this->getLevel(), $this->asVector3(), $item)); - return true; - } - - return false; + protected function getTileClass() : ?string{ + return TileEnchantingTable::class; } public function getHardness() : float{ diff --git a/src/pocketmine/block/EnderChest.php b/src/pocketmine/block/EnderChest.php index 1bde46ab2..34f6e68b6 100644 --- a/src/pocketmine/block/EnderChest.php +++ b/src/pocketmine/block/EnderChest.php @@ -27,15 +27,17 @@ use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\item\TieredTool; use pocketmine\math\Facing; -use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\EnderChest as TileEnderChest; -use pocketmine\tile\TileFactory; class EnderChest extends Chest{ protected $id = self::ENDER_CHEST; + protected function getTileClass() : ?string{ + return TileEnderChest::class; + } + public function getHardness() : float{ return 22.5; } @@ -60,19 +62,6 @@ class EnderChest extends Chest{ return TieredTool::TIER_WOODEN; } - public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ - if($player !== null){ //same as normal chest - TODO: clean up inheritance here - $this->facing = Facing::opposite($player->getHorizontalFacing()); - } - - if(Block::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - $this->level->addTile(TileFactory::createFromItem(TileEnderChest::class, $this->getLevel(), $this->asVector3(), $item)); - return true; - } - - return false; - } - public function onActivate(Item $item, Player $player = null) : bool{ if($player instanceof Player){ $enderChest = $this->getLevel()->getTile($this); diff --git a/src/pocketmine/block/FlowerPot.php b/src/pocketmine/block/FlowerPot.php index 4b24d626a..c3061f8b1 100644 --- a/src/pocketmine/block/FlowerPot.php +++ b/src/pocketmine/block/FlowerPot.php @@ -29,7 +29,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\FlowerPot as TileFlowerPot; -use pocketmine\tile\TileFactory; class FlowerPot extends Flowable{ @@ -55,6 +54,10 @@ class FlowerPot extends Flowable{ return 0b1111; //vanilla uses various values, we only care about 1 and 0 for PE } + protected function getTileClass() : ?string{ + return TileFlowerPot::class; + } + public function getName() : string{ return "Flower Pot"; } @@ -68,12 +71,7 @@ class FlowerPot extends Flowable{ return false; } - if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - $this->level->addTile(TileFactory::createFromItem(TileFlowerPot::class, $this->getLevel(), $this->asVector3(), $item)); - return true; - } - - return false; + return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } public function onNearbyBlockChange() : void{ diff --git a/src/pocketmine/block/Furnace.php b/src/pocketmine/block/Furnace.php index 031accfad..3f3882956 100644 --- a/src/pocketmine/block/Furnace.php +++ b/src/pocketmine/block/Furnace.php @@ -30,7 +30,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\Furnace as TileFurnace; -use pocketmine\tile\TileFactory; class Furnace extends Solid{ @@ -61,6 +60,10 @@ class Furnace extends Solid{ return 0b111; } + protected function getTileClass() : ?string{ + return TileFurnace::class; + } + public function getName() : string{ return "Furnace"; } @@ -99,12 +102,8 @@ class Furnace extends Solid{ if($player !== null){ $this->facing = Facing::opposite($player->getHorizontalFacing()); } - if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - $this->level->addTile(TileFactory::createFromItem(TileFurnace::class, $this->getLevel(), $this->asVector3(), $item)); - return true; - } - return false; + return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } public function onActivate(Item $item, Player $player = null) : bool{ diff --git a/src/pocketmine/block/ItemFrame.php b/src/pocketmine/block/ItemFrame.php index 827d7c2ba..583e85b3f 100644 --- a/src/pocketmine/block/ItemFrame.php +++ b/src/pocketmine/block/ItemFrame.php @@ -29,7 +29,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\ItemFrame as TileItemFrame; -use pocketmine\tile\TileFactory; use function lcg_value; class ItemFrame extends Flowable{ @@ -56,6 +55,10 @@ class ItemFrame extends Flowable{ return 0b11; } + protected function getTileClass() : ?string{ + return TileItemFrame::class; + } + public function getName() : string{ return "Item Frame"; } @@ -86,13 +89,7 @@ class ItemFrame extends Flowable{ $this->facing = $face; - if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - $this->level->addTile(TileFactory::createFromItem(TileItemFrame::class, $this->getLevel(), $this->asVector3(), $item)); - return true; - } - - return false; - + return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } public function getDropsForCompatibleTool(Item $item) : array{ diff --git a/src/pocketmine/block/SignPost.php b/src/pocketmine/block/SignPost.php index d9d05131b..e069472ea 100644 --- a/src/pocketmine/block/SignPost.php +++ b/src/pocketmine/block/SignPost.php @@ -29,7 +29,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\Sign as TileSign; -use pocketmine\tile\TileFactory; use function floor; class SignPost extends Transparent{ @@ -57,6 +56,10 @@ class SignPost extends Transparent{ return 0b1111; } + protected function getTileClass() : ?string{ + return TileSign::class; + } + public function getHardness() : float{ return 1; } @@ -78,15 +81,10 @@ class SignPost extends Transparent{ if($face === Facing::UP){ $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{ - $ret = $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_SIGN, $face)); + return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - if($ret){ - $this->level->addTile(TileFactory::createFromItem(TileSign::class, $this->getLevel(), $this->asVector3(), $item)); - return true; - } + return $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_SIGN, $face)); } return false; diff --git a/src/pocketmine/block/Skull.php b/src/pocketmine/block/Skull.php index 156ed0da7..acce6c4c4 100644 --- a/src/pocketmine/block/Skull.php +++ b/src/pocketmine/block/Skull.php @@ -31,7 +31,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\Skull as TileSkull; -use pocketmine\tile\TileFactory; use function floor; class Skull extends Flowable{ @@ -70,13 +69,18 @@ class Skull extends Flowable{ } } + protected function getTileClass() : ?string{ + return TileSkull::class; + } + public function writeStateToWorld() : void{ parent::writeStateToWorld(); - /** @var TileSkull $tile */ - $tile = TileFactory::create(TileSkull::class, $this->getLevel(), $this->asVector3()); - $tile->setRotation($this->rotation); - $tile->setType($this->type); - $this->level->addTile($tile); + //extra block properties storage hack + $tile = $this->level->getTile($this); + if($tile instanceof TileSkull){ + $tile->setRotation($this->rotation); + $tile->setType($this->type); + } } public function getHardness() : float{ diff --git a/src/pocketmine/block/StandingBanner.php b/src/pocketmine/block/StandingBanner.php index ff58a176e..7679a1039 100644 --- a/src/pocketmine/block/StandingBanner.php +++ b/src/pocketmine/block/StandingBanner.php @@ -31,7 +31,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\tile\Banner as TileBanner; -use pocketmine\tile\TileFactory; use function floor; class StandingBanner extends Transparent{ @@ -59,6 +58,10 @@ class StandingBanner extends Transparent{ return 0b1111; } + protected function getTileClass() : ?string{ + return TileBanner::class; + } + public function getHardness() : float{ return 1; } @@ -79,15 +82,10 @@ class StandingBanner extends Transparent{ if($face !== Facing::DOWN){ if($face === Facing::UP and $player !== null){ $this->rotation = ((int) floor((($player->yaw + 180) * 16 / 360) + 0.5)) & 0x0f; - $ret = parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); - }else{ - $ret = $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_BANNER, $face)); + return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player); } - if($ret){ - $this->level->addTile(TileFactory::createFromItem(TileBanner::class, $this->getLevel(), $this->asVector3(), $item)); - return true; - } + return $this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_BANNER, $face)); } return false; diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 5734e85dc..c8ee60798 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -1869,6 +1869,11 @@ class Level implements ChunkManager, Metadatable{ if(!$hand->place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ return false; } + $tile = $this->getTile($hand); + if($tile !== null){ + //TODO: seal this up inside block placement + $tile->copyDataFromItem($item); + } if($playSound){ $this->broadcastLevelSoundEvent($hand, LevelSoundEventPacket::SOUND_PLACE, $hand->getRuntimeId()); diff --git a/src/pocketmine/tile/Banner.php b/src/pocketmine/tile/Banner.php index 3266236fb..b799cc713 100644 --- a/src/pocketmine/tile/Banner.php +++ b/src/pocketmine/tile/Banner.php @@ -36,7 +36,7 @@ use function assert; class Banner extends Spawnable implements Nameable{ use NameableTrait { addAdditionalSpawnData as addNameSpawnData; - copyDataFromItem as copyNameFromItem; + copyDataFromItem as protected copyNameFromItem; } public const TAG_BASE = "Base";