From c79a5509f64b61d95e61b6435916d0f9eb25c455 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 26 Sep 2017 18:56:43 +0100 Subject: [PATCH] Implemented concrete powder this is a little buggy with water updating due to a hack for liquids to fix a CPU leak (210bdc2436269ca4d634aa791b1054e594769baa), but everything works fine when a block nearby gets updated. --- src/pocketmine/block/BlockFactory.php | 2 +- src/pocketmine/block/ConcretePowder.php | 74 +++++++++++++++++++++++++ src/pocketmine/block/Fallable.php | 9 ++- src/pocketmine/entity/FallingSand.php | 51 +++++++++++------ 4 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 src/pocketmine/block/ConcretePowder.php diff --git a/src/pocketmine/block/BlockFactory.php b/src/pocketmine/block/BlockFactory.php index c14322fb8..074b1cc94 100644 --- a/src/pocketmine/block/BlockFactory.php +++ b/src/pocketmine/block/BlockFactory.php @@ -302,7 +302,7 @@ class BlockFactory{ 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()); - //TODO: CONCRETEPOWDER + self::registerBlock(new ConcretePowder()); //TODO: CHORUS_PLANT self::registerBlock(new StainedGlass()); diff --git a/src/pocketmine/block/ConcretePowder.php b/src/pocketmine/block/ConcretePowder.php new file mode 100644 index 000000000..03f3770f2 --- /dev/null +++ b/src/pocketmine/block/ConcretePowder.php @@ -0,0 +1,74 @@ +meta = $meta; + } + + public function getName() : string{ + return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete Powder"; + } + + public function getHardness() : float{ + return 0.5; + } + + public function onUpdate(int $type){ + if($type === Level::BLOCK_UPDATE_NORMAL and ($block = $this->checkAdjacentWater()) !== null){ + $this->level->setBlock($this, $block); + return $type; + } + + return parent::onUpdate($type); + } + + /** + * @return null|Block + */ + public function tickFalling() : ?Block{ + return $this->checkAdjacentWater(); + } + + /** + * @return null|Block + */ + private function checkAdjacentWater(){ + for($i = 1; $i < 6; ++$i){ //Do not check underneath + if($this->getSide($i) instanceof Water){ + return Block::get(Block::CONCRETE, $this->meta); + } + } + + return null; + } +} \ No newline at end of file diff --git a/src/pocketmine/block/Fallable.php b/src/pocketmine/block/Fallable.php index 748585d77..95a7a5e71 100644 --- a/src/pocketmine/block/Fallable.php +++ b/src/pocketmine/block/Fallable.php @@ -39,7 +39,7 @@ abstract class Fallable extends Solid{ if($type === Level::BLOCK_UPDATE_NORMAL){ $down = $this->getSide(Vector3::SIDE_DOWN); if($down->getId() === self::AIR or ($down instanceof Liquid)){ - $this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true); + $this->level->setBlock($this, BlockFactory::get(Block::AIR), true); $fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [ new ListTag("Pos", [ new DoubleTag("", $this->x + 0.5), @@ -63,4 +63,11 @@ abstract class Fallable extends Solid{ } } } + + /** + * @return null|Block + */ + public function tickFalling() : ?Block{ + return null; + } } \ No newline at end of file diff --git a/src/pocketmine/entity/FallingSand.php b/src/pocketmine/entity/FallingSand.php index 57f4843ea..a17c3bc3b 100644 --- a/src/pocketmine/entity/FallingSand.php +++ b/src/pocketmine/entity/FallingSand.php @@ -23,10 +23,12 @@ declare(strict_types=1); namespace pocketmine\entity; -use pocketmine\block\BlockFactory; +use pocketmine\block\Block; +use pocketmine\block\Fallable; use pocketmine\event\entity\EntityBlockChangeEvent; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\item\ItemFactory; +use pocketmine\level\Position; use pocketmine\math\Vector3; use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\IntTag; @@ -43,30 +45,37 @@ class FallingSand extends Entity{ protected $gravity = 0.04; protected $drag = 0.02; - protected $blockId = 0; - protected $damage; + + /** @var Block */ + protected $block; public $canCollide = false; protected function initEntity(){ parent::initEntity(); + + $blockId = 0; + $damage = 0; + if(isset($this->namedtag->TileID)){ - $this->blockId = $this->namedtag["TileID"]; + $blockId = (int) $this->namedtag["TileID"]; }elseif(isset($this->namedtag->Tile)){ - $this->blockId = $this->namedtag["Tile"]; - $this->namedtag["TileID"] = new IntTag("TileID", $this->blockId); + $blockId = (int) $this->namedtag["Tile"]; + $this->namedtag["TileID"] = new IntTag("TileID", $blockId); } if(isset($this->namedtag->Data)){ - $this->damage = $this->namedtag["Data"]; + $damage = (int) $this->namedtag["Data"]; } - if($this->blockId === 0){ + if($blockId === 0){ $this->close(); return; } - $this->setDataProperty(self::DATA_VARIANT, self::DATA_TYPE_INT, $this->getBlock() | ($this->getDamage() << 8)); + $this->block = Block::get($blockId, $damage); + + $this->setDataProperty(self::DATA_VARIANT, self::DATA_TYPE_INT, $this->block->getId() | ($this->block->getDamage() << 8)); } public function canCollideWith(Entity $entity) : bool{ @@ -87,16 +96,24 @@ class FallingSand extends Entity{ $hasUpdate = parent::entityBaseTick($tickDiff); if($this->isAlive()){ - $pos = (new Vector3($this->x - 0.5, $this->y, $this->z - 0.5))->floor(); + $pos = Position::fromObject($this->add(-0.5, $this->height, -0.5)->floor(), $this->getLevel()); - if($this->onGround){ + $this->block->position($pos); + + $blockTarget = null; + if($this->block instanceof Fallable){ + $blockTarget = $this->block->tickFalling(); + } + + if($this->onGround or $blockTarget !== null){ $this->kill(); + $block = $this->level->getBlock($pos); if($block->getId() > 0 and $block->isTransparent() and !$block->canBeReplaced()){ //FIXME: anvils are supposed to destroy torches - $this->getLevel()->dropItem($this, ItemFactory::get($this->getBlock(), $this->getDamage(), 1)); + $this->getLevel()->dropItem($this, ItemFactory::get($this->getBlock(), $this->getDamage())); }else{ - $this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, BlockFactory::get($this->getBlock(), $this->getDamage()))); + $this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, $blockTarget ?? $this->block)); if(!$ev->isCancelled()){ $this->getLevel()->setBlock($pos, $ev->getTo(), true); } @@ -109,16 +126,16 @@ class FallingSand extends Entity{ } public function getBlock(){ - return $this->blockId; + return $this->block->getId(); } public function getDamage(){ - return $this->damage; + return $this->block->getDamage(); } public function saveNBT(){ - $this->namedtag->TileID = new IntTag("TileID", $this->blockId); - $this->namedtag->Data = new ByteTag("Data", $this->damage); + $this->namedtag->TileID = new IntTag("TileID", $this->block->getId()); + $this->namedtag->Data = new ByteTag("Data", $this->block->getDamage()); } public function spawnTo(Player $player){