Automate creation and deletion of Tiles for appropriate blocks

closes #880
This commit is contained in:
Dylan K. Taylor 2019-02-13 12:27:13 +00:00
parent 260c5dcf00
commit 01e7ebeb5c
13 changed files with 100 additions and 97 deletions

View File

@ -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{

View File

@ -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));
}

View File

@ -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;

View File

@ -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{

View File

@ -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);

View File

@ -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{

View File

@ -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{

View File

@ -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{

View File

@ -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;

View File

@ -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{

View File

@ -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;

View File

@ -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());

View File

@ -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";