Block: Split onUpdate() into several functions, removed Level::BLOCK_UPDATE_* constants

This allows the removal of lots of ugly code, and also exposes lots of similarities with how this update type was handled. This can be further improved in the future to more generically handle cases.

I realized in the process of changing this, that it might actually be simpler to treat to treat scheduled updates and neighbour updates as one and the same. They use the same mechanism for being saved on chunks (TileTicks),
and doing that would make updating only require one queue instead of two.

RedstoneOre: use onActivate() to trigger glowing
this is not technically correct behaviour, but this preserves the current behaviour.
This commit is contained in:
Dylan K. Taylor 2018-03-13 17:29:46 +00:00
parent 4f20a504e3
commit 86eee429bb
44 changed files with 490 additions and 765 deletions

View File

@ -278,6 +278,12 @@ class Block extends Position implements BlockIds, Metadatable{
return $base;
}
/**
* Called when this block or a block immediately adjacent to it changes state.
*/
public function onNearbyBlockChange() : void{
}
/**
* Returns whether random block updates will be done on this block.
@ -289,14 +295,18 @@ class Block extends Position implements BlockIds, Metadatable{
}
/**
* Fires a block update on the Block
*
* @param int $type
*
* @return bool|int
* Called when this block is randomly updated due to chunk ticking.
* WARNING: This will not be called if ticksRandomly() does not return true!
*/
public function onUpdate(int $type){
return false;
public function onRandomTick() : void{
}
/**
* Called when this block is updated by the delayed blockupdate scheduler in the level.
*/
public function onScheduledUpdate() : void{
}
/**

View File

@ -28,7 +28,6 @@ use pocketmine\event\block\BlockGrowEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -66,52 +65,49 @@ class Cactus extends Transparent{
);
}
public function ticksRandomly() : bool{
return true;
}
public function onEntityCollide(Entity $entity) : void{
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
$entity->attack($ev);
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
$this->getLevel()->useBreakOn($this);
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if(!$b->canBeFlowedInto()){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
if($this->meta === 0x0f){
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}
}
}
$this->meta = 0;
$this->getLevel()->setBlock($this, $this);
}else{
++$this->meta;
$this->getLevel()->setBlock($this, $this);
break;
}
}
}
}
return false;
public function ticksRandomly() : bool{
return true;
}
public function onRandomTick() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
if($this->meta === 0x0f){
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}
}
}
$this->meta = 0;
$this->getLevel()->setBlock($this, $this);
}else{
++$this->meta;
$this->getLevel()->setBlock($this, $this);
}
}
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -27,7 +27,6 @@ use pocketmine\entity\EffectInstance;
use pocketmine\entity\Living;
use pocketmine\item\FoodSource;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -73,16 +72,10 @@ class Cake extends Transparent implements FoodSource{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
}
return false;
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\block\utils\ColorBlockMetaHelper;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -73,16 +72,10 @@ class Carpet extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
}
return false;
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorBlockMetaHelper;
use pocketmine\level\Level;
class ConcretePowder extends Fallable{
@ -46,13 +45,10 @@ class ConcretePowder extends Fallable{
return BlockToolType::TYPE_SHOVEL;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL and ($block = $this->checkAdjacentWater()) !== null){
public function onNearbyBlockChange() : void{
if(($block = $this->checkAdjacentWater()) !== null){
$this->level->setBlock($this, $block);
return $type;
}
return parent::onUpdate($type);
}
/**

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
@ -65,35 +64,28 @@ abstract class Crops extends Flowable{
return false;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
$this->getLevel()->useBreakOn($this);
}
}
public function ticksRandomly() : bool{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(mt_rand(0, 2) === 1){
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
public function onRandomTick() : void{
if(mt_rand(0, 2) === 1){
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
}else{
return Level::BLOCK_UPDATE_RANDOM;
}
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
}
}else{
return Level::BLOCK_UPDATE_RANDOM;
}
}
return false;
}
public function isAffectedBySilkTouch() : bool{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -52,15 +51,9 @@ class Dandelion extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}
return false;
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
class DeadBush extends Flowable{
@ -40,16 +39,10 @@ class DeadBush extends Flowable{
return "Dead Bush";
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function getToolType() : int{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\level\sound\DoorSound;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -201,19 +200,13 @@ abstract class Door extends Transparent{
return $bb;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
}
return Level::BLOCK_UPDATE_NORMAL;
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
}
}
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -84,17 +83,10 @@ class DoublePlant extends Flowable{
);
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $down->isTransparent())){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function getVariantBitmask() : int{

View File

@ -24,26 +24,23 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
abstract class Fallable extends Solid{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
public function onNearbyBlockChange() : void{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
$nbt->setInt("TileID", $this->getId());
$nbt->setByte("Data", $this->getDamage());
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
$nbt->setInt("TileID", $this->getId());
$nbt->setByte("Data", $this->getDamage());
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
if($fall !== null){
$fall->spawnToAll();
}
if($fall !== null){
$fall->spawnToAll();
}
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -49,9 +48,6 @@ class Farmland extends Transparent{
return BlockToolType::TYPE_SHOVEL;
}
public function ticksRandomly() : bool{
return true;
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
@ -64,29 +60,28 @@ class Farmland extends Transparent{
);
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
return $type;
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(!$this->canHydrate()){
if($this->meta > 0){
$this->meta--;
$this->level->setBlock($this, $this, false, false);
}else{
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
}
return $type;
}elseif($this->meta < 7){
$this->meta = 7;
$this->level->setBlock($this, $this, false, false);
return $type;
}
}
}
return false;
public function ticksRandomly() : bool{
return true;
}
public function onRandomTick() : void{
if(!$this->canHydrate()){
if($this->meta > 0){
$this->meta--;
$this->level->setBlock($this, $this, false, false);
}else{
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
}
}elseif($this->meta < 7){
$this->meta = 7;
$this->level->setBlock($this, $this, false, false);
}
}
protected function canHydrate() : bool{

View File

@ -29,7 +29,6 @@ use pocketmine\event\entity\EntityCombustByBlockEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Server;
@ -61,10 +60,6 @@ class Fire extends Flowable{
return true;
}
public function ticksRandomly() : bool{
return true;
}
public function onEntityCollide(Entity $entity) : void{
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
$entity->attack($ev);
@ -83,35 +78,33 @@ class Fire extends Flowable{
return [];
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
for($s = 0; $s <= 5; ++$s){
$side = $this->getSide($s);
if($side->getId() !== self::AIR and !($side instanceof Liquid)){
return false;
}
public function onNearbyBlockChange() : void{
for($s = 0; $s <= 5; ++$s){
$side = $this->getSide($s);
if($side->getId() !== self::AIR and !($side instanceof Liquid)){
return;
}
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
return Level::BLOCK_UPDATE_NORMAL;
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::NETHERRACK){
if(mt_rand(0, 2) === 0){
if($this->meta === 0x0F){
$this->level->setBlock($this, BlockFactory::get(Block::AIR));
}else{
$this->meta++;
$this->level->setBlock($this, $this);
}
return Level::BLOCK_UPDATE_NORMAL;
}
}
//TODO: fire spread
}
return false;
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
}
public function ticksRandomly() : bool{
return true;
}
public function onRandomTick() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::NETHERRACK){
if(mt_rand(0, 2) === 0){
if($this->meta === 0x0F){
$this->level->setBlock($this, BlockFactory::get(Block::AIR));
}else{
$this->meta++;
$this->level->setBlock($this, $this);
}
}
}
//TODO: fire spread
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -71,15 +70,9 @@ class Flower extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}
return false;
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -68,16 +67,10 @@ class FlowerPot extends Flowable{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function onActivate(Item $item, Player $player = null) : bool{

View File

@ -23,8 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\level\Level;
class GlowingRedstoneOre extends RedstoneOre{
protected $id = self::GLOWING_REDSTONE_ORE;
@ -39,13 +37,11 @@ class GlowingRedstoneOre extends RedstoneOre{
return 9;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_SCHEDULED or $type === Level::BLOCK_UPDATE_RANDOM){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
public function ticksRandomly() : bool{
return true;
}
return Level::BLOCK_UPDATE_WEAK;
}
return false;
public function onRandomTick() : void{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
}
}

View File

@ -27,7 +27,6 @@ use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\utils\Random;
@ -62,43 +61,35 @@ class Grass extends Solid{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_RANDOM){
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
//grass dies
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT)));
public function onRandomTick() : void{
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
//grass dies
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT)));
if(!$ev->isCancelled()){
$this->level->setBlock($this, $ev->getNewState(), false, false);
}
}elseif($lightAbove >= 9){
//try grass spread
for($i = 0; $i < 4; ++$i){
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 3, $this->y + 1);
$z = mt_rand($this->z - 1, $this->z + 1);
if(
$this->level->getBlockIdAt($x, $y, $z) !== Block::DIRT or
$this->level->getBlockDataAt($x, $y, $z) === 1 or
$this->level->getFullLightAt($x, $y + 1, $z) < 4 or
BlockFactory::$lightFilter[$this->level->getBlockIdAt($x, $y + 1, $z)] >= 3
){
continue;
}
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS)));
if(!$ev->isCancelled()){
$this->level->setBlock($this, $ev->getNewState(), false, false);
$this->level->setBlock($b, $ev->getNewState(), false, false);
}
return Level::BLOCK_UPDATE_RANDOM;
}elseif($lightAbove >= 9){
//try grass spread
for($i = 0; $i < 4; ++$i){
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 3, $this->y + 1);
$z = mt_rand($this->z - 1, $this->z + 1);
if(
$this->level->getBlockIdAt($x, $y, $z) !== Block::DIRT or
$this->level->getBlockDataAt($x, $y, $z) === 1 or
$this->level->getFullLightAt($x, $y + 1, $z) < 4 or
BlockFactory::$lightFilter[$this->level->getBlockIdAt($x, $y + 1, $z)] >= 3
){
continue;
}
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS)));
if(!$ev->isCancelled()){
$this->level->setBlock($b, $ev->getNewState(), false, false);
}
}
return Level::BLOCK_UPDATE_RANDOM;
}
}
return false;
}
public function onActivate(Item $item, Player $player = null) : bool{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -60,13 +59,10 @@ class GrassPath extends Transparent{
return 0.6;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
return $type;
}
return false;
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\Player;
class Ice extends Transparent{
@ -67,15 +66,10 @@ class Ice extends Transparent{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_RANDOM){
if($this->level->getHighestAdjacentBlockLight($this->x, $this->y, $this->z) >= 12){
$this->level->useBreakOn($this);
return $type;
}
public function onRandomTick() : void{
if($this->level->getHighestAdjacentBlockLight($this->x, $this->y, $this->z) >= 12){
$this->level->useBreakOn($this);
}
return false;
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\tile\ItemFrame as TileItemFrame;
@ -58,20 +57,16 @@ class ItemFrame extends Flowable{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$sides = [
0 => Vector3::SIDE_WEST,
1 => Vector3::SIDE_EAST,
2 => Vector3::SIDE_NORTH,
3 => Vector3::SIDE_SOUTH
];
if(!$this->getSide($sides[$this->meta])->isSolid()){
$this->level->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
$sides = [
0 => Vector3::SIDE_WEST,
1 => Vector3::SIDE_EAST,
2 => Vector3::SIDE_NORTH,
3 => Vector3::SIDE_SOUTH
];
if(!$this->getSide($sides[$this->meta])->isSolid()){
$this->level->useBreakOn($this);
}
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -109,15 +108,10 @@ class Ladder extends Transparent{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method
$this->level->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method
$this->level->useBreakOn($this);
}
return false;
}
public function getToolType() : int{

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\event\block\LeavesDecayEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -67,9 +66,6 @@ class Leaves extends Transparent{
return true;
}
public function ticksRandomly() : bool{
return true;
}
protected function findLog(Block $pos, array $visited, $distance, &$check, $fromSide = null){
++$check;
@ -136,31 +132,31 @@ class Leaves extends Transparent{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if(($this->meta & 0b00001100) === 0){
$this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, true, false);
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(($this->meta & 0b00001100) === 0x08){
$this->meta &= 0x03;
$visited = [];
$check = 0;
public function onNearbyBlockChange() : void{
if(($this->meta & 0b00001100) === 0){
$this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, true, false);
}
}
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
public function ticksRandomly() : bool{
return true;
}
if($ev->isCancelled() or $this->findLog($this, $visited, 0, $check) === true){
$this->getLevel()->setBlock($this, $this, false, false);
}else{
$this->getLevel()->useBreakOn($this);
public function onRandomTick() : void{
if(($this->meta & 0b00001100) === 0x08){
$this->meta &= 0x03;
$visited = [];
$check = 0;
return Level::BLOCK_UPDATE_NORMAL;
}
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
if($ev->isCancelled() or $this->findLog($this, $visited, 0, $check) === true){
$this->getLevel()->setBlock($this, $this, false, false);
}else{
$this->getLevel()->useBreakOn($this);
}
}
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -74,26 +73,20 @@ class Lever extends Flowable{
return $this->level->setBlock($blockReplace, $this, true, true);
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$faces = [
0 => Vector3::SIDE_UP,
1 => Vector3::SIDE_WEST,
2 => Vector3::SIDE_EAST,
3 => Vector3::SIDE_NORTH,
4 => Vector3::SIDE_SOUTH,
5 => Vector3::SIDE_DOWN,
6 => Vector3::SIDE_DOWN,
7 => Vector3::SIDE_UP
];
if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){
$this->level->useBreakOn($this);
return $type;
}
public function onNearbyBlockChange() : void{
$faces = [
0 => Vector3::SIDE_UP,
1 => Vector3::SIDE_WEST,
2 => Vector3::SIDE_EAST,
3 => Vector3::SIDE_NORTH,
4 => Vector3::SIDE_SOUTH,
5 => Vector3::SIDE_DOWN,
6 => Vector3::SIDE_DOWN,
7 => Vector3::SIDE_UP
];
if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){
$this->level->useBreakOn($this);
}
return false;
}
//TODO

View File

@ -206,101 +206,88 @@ abstract class Liquid extends Transparent{
return 1;
}
/**
* {@inheritdoc}
*
* @param int $type
*
* @return bool|int
*/
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$this->checkForHarden();
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
public function onNearbyBlockChange() : void{
$this->checkForHarden();
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
}
return $type;
}elseif($type === Level::BLOCK_UPDATE_SCHEDULED){
$decay = $this->getFlowDecay($this);
$multiplier = $this->getFlowDecayPerBlock();
public function onScheduledUpdate() : void{
$decay = $this->getFlowDecay($this);
$multiplier = $this->getFlowDecayPerBlock();
if($decay > 0){
$smallestFlowDecay = -100;
$this->adjacentSources = 0;
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
if($decay > 0){
$smallestFlowDecay = -100;
$this->adjacentSources = 0;
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
$newDecay = $smallestFlowDecay + $multiplier;
$newDecay = $smallestFlowDecay + $multiplier;
if($newDecay >= 8 or $smallestFlowDecay < 0){
$newDecay = -1;
}
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
$newDecay = $topFlowDecay | 0x08;
}
if($this->adjacentSources >= 2 and $this instanceof Water){
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
if($bottomBlock->isSolid()){
$newDecay = 0;
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
$newDecay = 0;
}
}
if($newDecay !== $decay){
$decay = $newDecay;
if($decay < 0){
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
}else{
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
}
}
if($newDecay >= 8 or $smallestFlowDecay < 0){
$newDecay = -1;
}
if($decay >= 0){
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
$newDecay = $topFlowDecay | 0x08;
}
if($this->adjacentSources >= 2 and $this instanceof Water){
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
$this->flowIntoBlock($bottomBlock, $decay | 0x08);
if($decay === 0 or !$bottomBlock->canBeFlowedInto()){
if($decay >= 8){
$adjacentDecay = 1;
}else{
$adjacentDecay = $decay + $multiplier;
}
if($adjacentDecay < 8){
$flags = $this->getOptimalFlowDirections();
if($flags[0]){
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay);
}
if($flags[1]){
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay);
}
if($flags[2]){
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay);
}
if($flags[3]){
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay);
}
}
if($bottomBlock->isSolid()){
$newDecay = 0;
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
$newDecay = 0;
}
$this->checkForHarden();
}
return $type;
if($newDecay !== $decay){
$decay = $newDecay;
if($decay < 0){
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
}else{
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
}
}
}
return false;
if($decay >= 0){
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
$this->flowIntoBlock($bottomBlock, $decay | 0x08);
if($decay === 0 or !$bottomBlock->canBeFlowedInto()){
if($decay >= 8){
$adjacentDecay = 1;
}else{
$adjacentDecay = $decay + $multiplier;
}
if($adjacentDecay < 8){
$flags = $this->getOptimalFlowDirections();
if($flags[0]){
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay);
}
if($flags[1]){
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay);
}
if($flags[2]){
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay);
}
if($flags[3]){
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay);
}
}
}
$this->checkForHarden();
}
}
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Server;
@ -42,45 +41,32 @@ class MelonStem extends Crops{
$this->meta = $meta;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(mt_rand(0, 2) === 1){
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
public function onRandomTick() : void{
if(mt_rand(0, 2) === 1){
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
}
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b->getId() === self::MELON_BLOCK){
return;
}
}
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
}
return Level::BLOCK_UPDATE_RANDOM;
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b->getId() === self::MELON_BLOCK){
return Level::BLOCK_UPDATE_RANDOM;
}
}
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}
}
}
return Level::BLOCK_UPDATE_RANDOM;
}
return false;
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Server;
@ -60,19 +59,17 @@ class Mycelium extends Solid{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_RANDOM){
//TODO: light levels
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 2, $this->y + 2);
$z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockAt($x, $y, $z);
if($block->getId() === Block::DIRT){
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($block, $ev->getNewState());
}
public function onRandomTick() : void{
//TODO: light levels
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 2, $this->y + 2);
$z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockAt($x, $y, $z);
if($block->getId() === Block::DIRT){
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($block, $ev->getNewState());
}
}
}

View File

@ -27,7 +27,6 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -44,10 +43,6 @@ class NetherWartPlant extends Flowable{
return "Nether Wart";
}
public function ticksRandomly() : bool{
return true;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::SOUL_SAND){
@ -59,30 +54,26 @@ class NetherWartPlant extends Flowable{
return false;
}
public function onUpdate(int $type){
switch($type){
case Level::BLOCK_UPDATE_RANDOM:
if($this->meta < 3 and mt_rand(0, 10) === 0){ //Still growing
$block = clone $this;
$block->meta++;
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), false, true);
return $type;
}
}
break;
case Level::BLOCK_UPDATE_NORMAL:
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){
$this->getLevel()->useBreakOn($this);
return $type;
}
break;
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){
$this->getLevel()->useBreakOn($this);
}
}
return false;
public function ticksRandomly() : bool{
return true;
}
public function onRandomTick() : void{
if($this->meta < 3 and mt_rand(0, 10) === 0){ //Still growing
$block = clone $this;
$block->meta++;
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), false, true);
}
}
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Server;
@ -42,45 +41,32 @@ class PumpkinStem extends Crops{
return "Pumpkin Stem";
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(mt_rand(0, 2) === 1){
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
public function onRandomTick() : void{
if(mt_rand(0, 2) === 1){
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
}
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b->getId() === self::PUMPKIN){
return;
}
}
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::PUMPKIN)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
}
return Level::BLOCK_UPDATE_RANDOM;
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b->getId() === self::PUMPKIN){
return Level::BLOCK_UPDATE_RANDOM;
}
}
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::PUMPKIN)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}
}
}
return Level::BLOCK_UPDATE_RANDOM;
}
return false;
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -63,17 +62,12 @@ class Rail extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
return $type;
}else{
//TODO: Update rail connectivity
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}else{
//TODO: Update rail connectivity
}
return false;
}
public function getVariantBitmask() : int{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -44,16 +43,10 @@ class RedMushroom extends Flowable{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\TieredTool;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -50,14 +49,12 @@ class RedstoneOre extends Solid{
return $this->getLevel()->setBlock($this, $this, true, false);
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL or $type === Level::BLOCK_UPDATE_TOUCH){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
public function onActivate(Item $item, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
}
return Level::BLOCK_UPDATE_WEAK;
}
return false;
public function onNearbyBlockChange() : void{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
}
public function getToolType() : int{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\generator\object\Tree;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\utils\Random;
@ -56,10 +55,6 @@ class Sapling extends Flowable{
return $names[$this->getVariant()] ?? "Unknown";
}
public function ticksRandomly() : bool{
return true;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::FARMLAND){
@ -84,29 +79,25 @@ class Sapling extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}
}
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){ //Growth
if(mt_rand(1, 7) === 1){
if(($this->meta & 0x08) === 0x08){
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant());
}else{
$this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, true);
public function ticksRandomly() : bool{
return true;
}
return Level::BLOCK_UPDATE_RANDOM;
}
public function onRandomTick() : void{
if(mt_rand(1, 7) === 1){
if(($this->meta & 0x08) === 0x08){
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant());
}else{
return Level::BLOCK_UPDATE_RANDOM;
$this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, true);
}
}
return false;
}
public function getVariantBitmask() : int{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -77,16 +76,10 @@ class SignPost extends Transparent{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function getToolType() : int{

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\TieredTool;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -58,10 +57,6 @@ class SnowLayer extends Flowable{
return TieredTool::TIER_WOODEN;
}
public function ticksRandomly() : bool{
return true;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($blockReplace->getSide(Vector3::SIDE_DOWN)->isSolid()){
//TODO: fix placement
@ -73,22 +68,20 @@ class SnowLayer extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid()){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->level->getBlockLightAt($this->x, $this->y, $this->z) >= 12){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
return Level::BLOCK_UPDATE_RANDOM;
}
public function onNearbyBlockChange() : void{
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid()){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
}
}
return false;
public function ticksRandomly() : bool{
return true;
}
public function onRandomTick() : void{
if($this->level->getBlockLightAt($this->x, $this->y, $this->z) >= 12){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
}
}
public function getDropsForCompatibleTool(Item $item) : array{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -75,16 +74,10 @@ class StandingBanner extends Transparent{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function getToolType() : int{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
@ -44,10 +43,6 @@ class Sugarcane extends Flowable{
return "Sugarcane";
}
public function ticksRandomly() : bool{
return true;
}
public function onActivate(Item $item, Player $player = null) : bool{
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::SUGARCANE_BLOCK){
@ -73,36 +68,34 @@ class Sugarcane extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->isTransparent() === true and $down->getId() !== self::SUGARCANE_BLOCK){
$this->getLevel()->useBreakOn($this);
public function onNearbyBlockChange() : void{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->isTransparent() and $down->getId() !== self::SUGARCANE_BLOCK){
$this->getLevel()->useBreakOn($this);
}
}
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::SUGARCANE_BLOCK){
if($this->meta === 0x0F){
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){
$this->getLevel()->setBlock($b, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
break;
}
public function ticksRandomly() : bool{
return true;
}
public function onRandomTick() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::SUGARCANE_BLOCK){
if($this->meta === 0x0F){
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){
$this->getLevel()->setBlock($b, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
break;
}
$this->meta = 0;
$this->getLevel()->setBlock($this, $this, true);
}else{
++$this->meta;
$this->getLevel()->setBlock($this, $this, true);
}
return Level::BLOCK_UPDATE_RANDOM;
$this->meta = 0;
$this->getLevel()->setBlock($this, $this, true);
}else{
++$this->meta;
$this->getLevel()->setBlock($this, $this, true);
}
}
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -61,17 +60,10 @@ class TallGrass extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
}
return false;
}
public function getToolType() : int{

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -44,28 +43,21 @@ class Torch extends Flowable{
return "Torch";
}
public function onNearbyBlockChange() : void{
$below = $this->getSide(Vector3::SIDE_DOWN);
$side = $this->getDamage();
$faces = [
0 => Vector3::SIDE_DOWN,
1 => Vector3::SIDE_WEST,
2 => Vector3::SIDE_EAST,
3 => Vector3::SIDE_NORTH,
4 => Vector3::SIDE_SOUTH,
5 => Vector3::SIDE_DOWN
];
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$below = $this->getSide(Vector3::SIDE_DOWN);
$side = $this->getDamage();
$faces = [
0 => Vector3::SIDE_DOWN,
1 => Vector3::SIDE_WEST,
2 => Vector3::SIDE_EAST,
3 => Vector3::SIDE_NORTH,
4 => Vector3::SIDE_SOUTH,
5 => Vector3::SIDE_DOWN
];
if($this->getSide($faces[$side])->isTransparent() === true and !($side === Vector3::SIDE_DOWN and ($below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL))){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
if($this->getSide($faces[$side])->isTransparent() and !($side === Vector3::SIDE_DOWN and ($below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL))){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -62,10 +61,6 @@ class Vine extends Flowable{
return true;
}
public function ticksRandomly() : bool{
return true;
}
public function canBeReplaced() : bool{
return true;
}
@ -157,42 +152,42 @@ class Vine extends Flowable{
return true;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$sides = [
self::FLAG_SOUTH => Vector3::SIDE_SOUTH,
self::FLAG_WEST => Vector3::SIDE_WEST,
self::FLAG_NORTH => Vector3::SIDE_NORTH,
self::FLAG_EAST => Vector3::SIDE_EAST
];
public function onNearbyBlockChange() : void{
$sides = [
self::FLAG_SOUTH => Vector3::SIDE_SOUTH,
self::FLAG_WEST => Vector3::SIDE_WEST,
self::FLAG_NORTH => Vector3::SIDE_NORTH,
self::FLAG_EAST => Vector3::SIDE_EAST
];
$meta = $this->meta;
$meta = $this->meta;
foreach($sides as $flag => $side){
if(($meta & $flag) === 0){
continue;
}
if(!$this->getSide($side)->isSolid()){
$meta &= ~$flag;
}
foreach($sides as $flag => $side){
if(($meta & $flag) === 0){
continue;
}
if($meta !== $this->meta){
if($meta === 0){
$this->level->useBreakOn($this);
}else{
$this->meta = $meta;
$this->level->setBlock($this, $this);
}
return Level::BLOCK_UPDATE_NORMAL;
if(!$this->getSide($side)->isSolid()){
$meta &= ~$flag;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
//TODO: vine growth
}
return false;
if($meta !== $this->meta){
if($meta === 0){
$this->level->useBreakOn($this);
}else{
$this->meta = $meta;
$this->level->setBlock($this, $this);
}
}
}
public function ticksRandomly() : bool{
return true;
}
public function onRandomTick() : void{
//TODO: vine growth
}
public function getVariantBitmask() : int{

View File

@ -23,8 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\level\Level;
class WallBanner extends StandingBanner{
protected $id = self::WALL_BANNER;
@ -33,13 +31,9 @@ class WallBanner extends StandingBanner{
return "Wall Banner";
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
}
return Level::BLOCK_UPDATE_NORMAL;
public function onNearbyBlockChange() : void{
if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
}
return false;
}
}

View File

@ -23,8 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\level\Level;
class WallSign extends SignPost{
protected $id = self::WALL_SIGN;
@ -33,13 +31,9 @@ class WallSign extends SignPost{
return "Wall Sign";
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
}
return Level::BLOCK_UPDATE_NORMAL;
public function onNearbyBlockChange() : void{
if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
}
return false;
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -69,15 +68,10 @@ class WaterLily extends Flowable{
return false;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if(!($this->getSide(Vector3::SIDE_DOWN) instanceof Water)){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
public function onNearbyBlockChange() : void{
if(!($this->getSide(Vector3::SIDE_DOWN) instanceof Water)){
$this->getLevel()->useBreakOn($this);
}
return false;
}
public function getVariantBitmask() : int{

View File

@ -236,7 +236,7 @@ class Explosion{
if(!isset($this->affectedBlocks[$index = Level::blockHash($sideBlock->x, $sideBlock->y, $sideBlock->z)]) and !isset($updateBlocks[$index])){
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->level->getBlockAt($sideBlock->x, $sideBlock->y, $sideBlock->z)));
if(!$ev->isCancelled()){
$ev->getBlock()->onUpdate(Level::BLOCK_UPDATE_NORMAL);
$ev->getBlock()->onNearbyBlockChange();
}
$updateBlocks[$index] = true;
}

View File

@ -96,12 +96,6 @@ class Level implements ChunkManager, Metadatable{
public const Y_MASK = 0xFF;
public const Y_MAX = 0x100; //256
public const BLOCK_UPDATE_NORMAL = 1;
public const BLOCK_UPDATE_RANDOM = 2;
public const BLOCK_UPDATE_SCHEDULED = 3;
public const BLOCK_UPDATE_WEAK = 4;
public const BLOCK_UPDATE_TOUCH = 5;
public const TIME_DAY = 0;
public const TIME_SUNSET = 12000;
public const TIME_NIGHT = 14000;
@ -743,7 +737,7 @@ class Level implements ChunkManager, Metadatable{
while($this->scheduledBlockUpdateQueue->count() > 0 and $this->scheduledBlockUpdateQueue->current()["priority"] <= $currentTick){
$block = $this->getBlock($this->scheduledBlockUpdateQueue->extract()["data"]);
unset($this->scheduledBlockUpdateQueueIndex[Level::blockHash($block->x, $block->y, $block->z)]);
$block->onUpdate(self::BLOCK_UPDATE_SCHEDULED);
$block->onScheduledUpdate();
}
//Normal updates
@ -756,7 +750,7 @@ class Level implements ChunkManager, Metadatable{
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block));
if(!$ev->isCancelled()){
$block->onUpdate(self::BLOCK_UPDATE_NORMAL);
$block->onNearbyBlockChange();
}
}
@ -1034,7 +1028,7 @@ class Level implements ChunkManager, Metadatable{
$block->y = ($Y << 4) + $y;
$block->z = $chunkZ * 16 + $z;
$block->level = $this;
$block->onUpdate(self::BLOCK_UPDATE_RANDOM);
$block->onRandomTick();
}
}
}
@ -1557,7 +1551,7 @@ class Level implements ChunkManager, Metadatable{
$entity->setForceMovementUpdate();
$entity->scheduleUpdate();
}
$ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
$ev->getBlock()->onNearbyBlockChange();
$this->scheduleNeighbourBlockUpdates($pos);
}
}
@ -1799,7 +1793,6 @@ class Level implements ChunkManager, Metadatable{
$this->server->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$blockClicked->onUpdate(self::BLOCK_UPDATE_TOUCH);
if(!$player->isSneaking() and $blockClicked->onActivate($item, $player) === true){
return true;
}