diff --git a/src/pocketmine/block/Bed.php b/src/pocketmine/block/Bed.php index 829196704..28aaa8b5d 100644 --- a/src/pocketmine/block/Bed.php +++ b/src/pocketmine/block/Bed.php @@ -86,9 +86,12 @@ class Bed extends Transparent{ public function writeStateToWorld() : void{ parent::writeStateToWorld(); //extra block properties storage hack - $tile = Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this)); - if($tile instanceof TileBed){ - $tile->setColor($this->color); + $tile = Tile::create(Tile::BED, $this->getLevel(), $this->asVector3()); + if($tile !== null){ + if($tile instanceof TileBed){ + $tile->setColor($this->color); + } + $this->level->addTile($tile); } } diff --git a/src/pocketmine/block/Chest.php b/src/pocketmine/block/Chest.php index 2a6de15a7..b577ff66b 100644 --- a/src/pocketmine/block/Chest.php +++ b/src/pocketmine/block/Chest.php @@ -92,7 +92,10 @@ class Chest extends Transparent{ } if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - $tile = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this, $item)); + $tile = Tile::createFromItem(Tile::CHEST, $this->getLevel(), $this->asVector3(), $item); + if($tile !== null){ + $this->level->addTile($tile); + } if($chest instanceof TileChest and $tile instanceof TileChest){ $chest->pairWith($tile); diff --git a/src/pocketmine/block/EnchantingTable.php b/src/pocketmine/block/EnchantingTable.php index 416ec5459..02c3059b1 100644 --- a/src/pocketmine/block/EnchantingTable.php +++ b/src/pocketmine/block/EnchantingTable.php @@ -30,7 +30,6 @@ use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; -use pocketmine\tile\EnchantTable as TileEnchantTable; use pocketmine\tile\Tile; class EnchantingTable extends Transparent{ @@ -43,7 +42,9 @@ 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)){ - Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), TileEnchantTable::createNBT($this, $item)); + if(($tile = Tile::createFromItem(Tile::ENCHANT_TABLE, $this->getLevel(), $this->asVector3(), $item)) !== null){ + $this->level->addTile($tile); + } return true; } diff --git a/src/pocketmine/block/EnderChest.php b/src/pocketmine/block/EnderChest.php index f58ce88b0..c810263a6 100644 --- a/src/pocketmine/block/EnderChest.php +++ b/src/pocketmine/block/EnderChest.php @@ -66,7 +66,9 @@ class EnderChest extends Chest{ } if(Block::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this, $item)); + if(($tile = Tile::createFromItem(Tile::ENDER_CHEST, $this->getLevel(), $this->asVector3(), $item)) !== null){ + $this->level->addTile($tile); + } return true; } diff --git a/src/pocketmine/block/FlowerPot.php b/src/pocketmine/block/FlowerPot.php index 14e48dec4..1c0350dd0 100644 --- a/src/pocketmine/block/FlowerPot.php +++ b/src/pocketmine/block/FlowerPot.php @@ -69,7 +69,9 @@ class FlowerPot extends Flowable{ } if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), TileFlowerPot::createNBT($this, $item)); + if(($tile = Tile::createFromItem(Tile::FLOWER_POT, $this->getLevel(), $this->asVector3(), $item)) !== null){ + $this->level->addTile($tile); + } return true; } diff --git a/src/pocketmine/block/Furnace.php b/src/pocketmine/block/Furnace.php index 38e8d91b1..b4a91ccf5 100644 --- a/src/pocketmine/block/Furnace.php +++ b/src/pocketmine/block/Furnace.php @@ -99,7 +99,9 @@ class Furnace extends Solid{ $this->facing = Facing::opposite($player->getHorizontalFacing()); } if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $item)); + if(($tile = Tile::createFromItem(Tile::FURNACE, $this->getLevel(), $this->asVector3(), $item)) !== null){ + $this->level->addTile($tile); + } return true; } diff --git a/src/pocketmine/block/ItemFrame.php b/src/pocketmine/block/ItemFrame.php index 772665c60..adbc93d07 100644 --- a/src/pocketmine/block/ItemFrame.php +++ b/src/pocketmine/block/ItemFrame.php @@ -85,7 +85,9 @@ class ItemFrame extends Flowable{ $this->facing = $face; if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){ - Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this, $item)); + if(($tile = Tile::createFromItem(Tile::ITEM_FRAME, $this->getLevel(), $this->asVector3(), $item)) !== null){ + $this->level->addTile($tile); + } return true; } diff --git a/src/pocketmine/block/SignPost.php b/src/pocketmine/block/SignPost.php index 8dd99035e..8f6e027d2 100644 --- a/src/pocketmine/block/SignPost.php +++ b/src/pocketmine/block/SignPost.php @@ -28,7 +28,6 @@ use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\Player; -use pocketmine\tile\Sign as TileSign; use pocketmine\tile\Tile; class SignPost extends Transparent{ @@ -83,7 +82,9 @@ class SignPost extends Transparent{ } if($ret){ - Tile::createTile(Tile::SIGN, $this->getLevel(), TileSign::createNBT($this, $item)); + if(($tile = Tile::createFromItem(Tile::SIGN, $this->getLevel(), $this->asVector3(), $item)) !== null){ + $this->level->addTile($tile); + } return true; } } diff --git a/src/pocketmine/block/Skull.php b/src/pocketmine/block/Skull.php index b49017bb5..7e54d629f 100644 --- a/src/pocketmine/block/Skull.php +++ b/src/pocketmine/block/Skull.php @@ -70,10 +70,13 @@ class Skull extends Flowable{ public function writeStateToWorld() : void{ parent::writeStateToWorld(); - $tile = Tile::createTile(Tile::SKULL, $this->getLevel(), TileSkull::createNBT($this)); - if($tile instanceof TileSkull){ - $tile->setRotation($this->rotation); - $tile->setType($this->type); + $tile = Tile::create(Tile::SKULL, $this->getLevel(), $this->asVector3()); + if($tile !== null){ + if($tile instanceof TileSkull){ + $tile->setRotation($this->rotation); + $tile->setType($this->type); + } + $this->level->addTile($tile); } } diff --git a/src/pocketmine/block/StandingBanner.php b/src/pocketmine/block/StandingBanner.php index 28898faa4..55745c29d 100644 --- a/src/pocketmine/block/StandingBanner.php +++ b/src/pocketmine/block/StandingBanner.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\item\Banner as ItemBanner; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\math\AxisAlignedBB; @@ -83,7 +84,17 @@ class StandingBanner extends Transparent{ } if($ret){ - Tile::createTile(Tile::BANNER, $this->getLevel(), TileBanner::createNBT($this, $item)); + $tile = Tile::createFromItem(Tile::BANNER, $this->getLevel(), $this->asVector3(), $item); + if($tile !== null){ + if($tile instanceof TileBanner and $item instanceof ItemBanner){ + $tile->setBaseColor($item->getBaseColor()); + if(($patterns = $item->getPatterns()) !== null){ + $tile->setPatterns($patterns); + } + } + + $this->level->addTile($tile); + } return true; } } @@ -105,8 +116,8 @@ class StandingBanner extends Transparent{ $tile = $this->level->getTile($this); $drop = ItemFactory::get(Item::BANNER, ($tile instanceof TileBanner ? $tile->getBaseColor() : 0)); - if($tile instanceof TileBanner and !($patterns = $tile->getPatterns())->empty()){ - $drop->setNamedTagEntry(clone $patterns); + if($tile instanceof TileBanner and $drop instanceof ItemBanner and !($patterns = $tile->getPatterns())->empty()){ + $drop->setPatterns($patterns); } return [$drop]; diff --git a/src/pocketmine/item/Banner.php b/src/pocketmine/item/Banner.php index 9dabb9306..d5ddb5e39 100644 --- a/src/pocketmine/item/Banner.php +++ b/src/pocketmine/item/Banner.php @@ -206,6 +206,20 @@ class Banner extends Item{ return $this->getNamedTag()->getListTag(self::TAG_PATTERNS)->count(); } + /** + * @return ListTag|null + */ + public function getPatterns() : ?ListTag{ + return $this->getNamedTag()->getListTag(self::TAG_PATTERNS); + } + + /** + * @param ListTag $patterns + */ + public function setPatterns(ListTag $patterns) : void{ + $this->setNamedTagEntry(clone $patterns); + } + public function correctNBT() : void{ $tag = $this->getNamedTag(); if(!$tag->hasTag(self::TAG_BASE, IntTag::class)){ diff --git a/src/pocketmine/level/format/Chunk.php b/src/pocketmine/level/format/Chunk.php index a457aeb0b..05ad16c4c 100644 --- a/src/pocketmine/level/format/Chunk.php +++ b/src/pocketmine/level/format/Chunk.php @@ -618,7 +618,9 @@ class Chunk{ continue; } - if(Tile::createTile($nbt->getString(Tile::TAG_ID), $level, $nbt) === null){ + if(($tile = Tile::createFromData($nbt->getString(Tile::TAG_ID), $level, $nbt)) !== null){ + $level->addTile($tile); + }else{ $changed = true; continue; } diff --git a/src/pocketmine/tile/Banner.php b/src/pocketmine/tile/Banner.php index af14afad0..c1ed28e69 100644 --- a/src/pocketmine/tile/Banner.php +++ b/src/pocketmine/tile/Banner.php @@ -23,8 +23,6 @@ declare(strict_types=1); namespace pocketmine\tile; -use pocketmine\item\Banner as ItemBanner; -use pocketmine\item\Item; use pocketmine\level\Level; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; @@ -35,7 +33,6 @@ use pocketmine\nbt\tag\StringTag; class Banner extends Spawnable implements Nameable{ use NameableTrait { addAdditionalSpawnData as addNameSpawnData; - createAdditionalNBT as createNameNBT; } public const TAG_BASE = "Base"; @@ -274,17 +271,9 @@ class Banner extends Spawnable implements Nameable{ return $this->patterns; } - protected static function createAdditionalNBT(CompoundTag $nbt, ?Item $item = null) : void{ - if($item instanceof ItemBanner){ - $nbt->setInt(self::TAG_BASE, $item->getBaseColor()); - - //TODO: clean this mess up - if($item->getNamedTag()->hasTag(self::TAG_PATTERNS, ListTag::class)){ - $nbt->setTag($item->getNamedTag()->getListTag(self::TAG_PATTERNS)); - } - - self::createNameNBT($nbt, $item); - } + public function setPatterns(ListTag $patterns) : void{ + $this->patterns = clone $patterns; + $this->onChanged(); } public function getDefaultName() : string{ diff --git a/src/pocketmine/tile/NameableTrait.php b/src/pocketmine/tile/NameableTrait.php index c65a679fd..90dd3d778 100644 --- a/src/pocketmine/tile/NameableTrait.php +++ b/src/pocketmine/tile/NameableTrait.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\tile; -use pocketmine\item\Item; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\StringTag; @@ -64,12 +63,6 @@ trait NameableTrait{ return $this->customName !== null; } - protected static function createAdditionalNBT(CompoundTag $nbt, ?Item $item = null) : void{ - if($item !== null and $item->hasCustomName()){ - $nbt->setString(Nameable::TAG_CUSTOM_NAME, $item->getCustomName()); - } - } - public function addAdditionalSpawnData(CompoundTag $nbt) : void{ if($this->customName !== null){ $nbt->setString(Nameable::TAG_CUSTOM_NAME, $this->customName); diff --git a/src/pocketmine/tile/Tile.php b/src/pocketmine/tile/Tile.php index 5cfcc52dd..f60f572a9 100644 --- a/src/pocketmine/tile/Tile.php +++ b/src/pocketmine/tile/Tile.php @@ -33,8 +33,6 @@ use pocketmine\level\Level; use pocketmine\level\Position; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\IntTag; -use pocketmine\nbt\tag\StringTag; use pocketmine\timings\Timings; use pocketmine\timings\TimingsHandler; use pocketmine\utils\Utils; @@ -88,21 +86,52 @@ abstract class Tile extends Position{ * @param string $type * @param Level $level * @param CompoundTag $nbt - * @param $args * * @return Tile|null */ - public static function createTile($type, Level $level, CompoundTag $nbt, ...$args) : ?Tile{ + public static function createFromData($type, Level $level, CompoundTag $nbt) : ?Tile{ + $tile = self::create($type, $level, new Vector3($nbt->getInt(self::TAG_X), $nbt->getInt(self::TAG_Y), $nbt->getInt(self::TAG_Z))); + if($tile !== null){ + $tile->readSaveData($nbt); + } + return $tile; + } + + /** + * @param string $type + * @param Level $level + * @param Vector3 $pos + * @param Item $item + * + * @return Tile|null + */ + public static function createFromItem(string $type, Level $level, Vector3 $pos, Item $item) : ?Tile{ + $tile = self::create($type, $level, $pos); + if($tile !== null and $item->hasCustomBlockData()){ + $tile->readSaveData($item->getCustomBlockData()); + } + if($tile instanceof Nameable and $item->hasCustomName()){ //this should take precedence over saved NBT + $tile->setName($item->getCustomName()); + } + + return $tile; + } + + /** + * @param string $type + * @param Level $level + * @param Vector3 $pos + * + * @return Tile|null + */ + public static function create(string $type, Level $level, Vector3 $pos) : ?Tile{ if(isset(self::$knownTiles[$type])){ - $pos = new Vector3($nbt->getInt(self::TAG_X), $nbt->getInt(self::TAG_Y), $nbt->getInt(self::TAG_Z)); $class = self::$knownTiles[$type]; /** * @var Tile $tile * @see Tile::__construct() */ $tile = new $class($level, $pos); - $tile->readSaveData($nbt); - $level->addTile($tile); return $tile; } @@ -176,53 +205,6 @@ abstract class Tile extends Position{ return $tag->getCount() > 0 ? $tag : null; } - /** - * Creates and returns a CompoundTag containing the necessary information to spawn a tile of this type. - * - * @param Vector3 $pos - * @param Item|null $item - * - * @return CompoundTag - * @throws \BadMethodCallException - * @throws \InvalidArgumentException - * @throws \InvalidStateException - */ - public static function createNBT(Vector3 $pos, ?Item $item = null) : CompoundTag{ - if(static::class === self::class){ - throw new \BadMethodCallException(__METHOD__ . " must be called from the scope of a child class"); - } - $nbt = new CompoundTag("", [ - new StringTag(self::TAG_ID, static::getSaveId()), - new IntTag(self::TAG_X, (int) $pos->x), - new IntTag(self::TAG_Y, (int) $pos->y), - new IntTag(self::TAG_Z, (int) $pos->z) - ]); - - static::createAdditionalNBT($nbt, $item); - - if($item !== null){ - $customBlockData = $item->getCustomBlockData(); - if($customBlockData !== null){ - foreach($customBlockData as $customBlockDataTag){ - $nbt->setTag(clone $customBlockDataTag); - } - } - } - - return $nbt; - } - - /** - * Called by createNBT() to allow descendent classes to add their own base NBT using the parameters provided. - * TODO: remove this and add a hook for setting data from items post-place - * - * @param CompoundTag $nbt - * @param Item|null $item - */ - protected static function createAdditionalNBT(CompoundTag $nbt, ?Item $item = null) : void{ - - } - /** * @return Block */