diff --git a/src/pocketmine/block/Block.php b/src/pocketmine/block/Block.php index ed2196a6a..e73a9492f 100644 --- a/src/pocketmine/block/Block.php +++ b/src/pocketmine/block/Block.php @@ -472,6 +472,14 @@ class Block extends Position implements BlockIds, Metadatable{ return false; } + /** + * Returns whether entities can climb up this block. + * @return bool + */ + public function canClimb() : bool{ + return false; + } + /** * @return string */ diff --git a/src/pocketmine/block/Ladder.php b/src/pocketmine/block/Ladder.php index c96d3bfff..c652dc20e 100644 --- a/src/pocketmine/block/Ladder.php +++ b/src/pocketmine/block/Ladder.php @@ -52,6 +52,10 @@ class Ladder extends Transparent{ return 0.4; } + public function canClimb() : bool{ + return true; + } + public function onEntityCollide(Entity $entity){ $entity->resetFallDistance(); $entity->onGround = true; diff --git a/src/pocketmine/block/Vine.php b/src/pocketmine/block/Vine.php index 6f8097d9b..84beb125b 100644 --- a/src/pocketmine/block/Vine.php +++ b/src/pocketmine/block/Vine.php @@ -56,6 +56,10 @@ class Vine extends Transparent{ return true; } + public function canClimb() : bool{ + return true; + } + public function onEntityCollide(Entity $entity){ $entity->resetFallDistance(); } @@ -122,7 +126,7 @@ class Vine extends Transparent{ public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){ - if(!$target->isTransparent() and $target->isSolid()){ + if($target->isSolid()){ $faces = [ 2 => 1, 3 => 4, @@ -142,11 +146,16 @@ class Vine extends Transparent{ public function onUpdate($type){ if($type === Level::BLOCK_UPDATE_NORMAL){ - /*if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method - Server::getInstance()->api->entity->drop($this, Item::get(LADDER, 0, 1)); - $this->getLevel()->setBlock($this, new Air(), true, true); + $sides = [ + 2 => 4, + 3 => 1, + 4 => 2, + 5 => 8 + ]; + if(!$this->getSide($sides[$this->meta])->isSolid()){ //Replace with common break method + $this->level->useBreakOn($this); return Level::BLOCK_UPDATE_NORMAL; - }*/ + } } return false; diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index e8b4e85aa..ade9188e5 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -454,6 +454,45 @@ abstract class Entity extends Location implements Metadatable{ $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_IMMOBILE, $value); } + /** + * Sets whether this entity is currently able to climb blocks. By default this is only true if the entity is climbing a ladder or vine or similar block. + * + * @return bool + */ + public function isClimbing() : bool{ + return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_WALLCLIMBING); + } + + /** + * Sets whether the entity can climb blocks. If true, the entity can climb anything, if false, they cannot climb anything (this includes ladders and vines). + * + * @param bool $value + */ + public function setClimbing(bool $value = true){ + $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_WALLCLIMBING, $value); + } + + /** + * Checks blocks adjacent to the entity's feet to check if it is currently colliding with a climbable block. + */ + protected function checkClimbing(){ + $climbing = false; + + $block = $this->level->getBlock($this); + if($block->canClimb()){ + $climbing = true; + }else{ + for($i = 0; $i <= 5; ++$i){ + if($block->getSide($i)->canClimb()){ + $climbing = true; + break; + } + } + } + + $this->setClimbing($climbing); + } + /** * @return Effect[] */ @@ -1434,6 +1473,7 @@ abstract class Entity extends Location implements Metadatable{ $this->checkChunks(); $this->checkGroundState($movX, $movY, $movZ, $dx, $dy, $dz); + $this->checkClimbing(); $this->updateFallState($dy, $this->onGround); if($movX != $dx){