treeType = $treeType; } public function getRequiredStateDataBits() : int{ return 2; } protected function decodeState(BlockDataReader $r) : void{ $this->noDecay = $r->readBool(); $this->checkDecay = $r->readBool(); } protected function encodeState(BlockDataWriter $w) : void{ $w->writeBool($this->noDecay); $w->writeBool($this->checkDecay); } public function isNoDecay() : bool{ return $this->noDecay; } /** @return $this */ public function setNoDecay(bool $noDecay) : self{ $this->noDecay = $noDecay; return $this; } public function isCheckDecay() : bool{ return $this->checkDecay; } /** @return $this */ public function setCheckDecay(bool $checkDecay) : self{ $this->checkDecay = $checkDecay; return $this; } public function blocksDirectSkyLight() : bool{ return true; } /** * @param true[] $visited reference parameter * @phpstan-param array $visited */ protected function findLog(Vector3 $pos, array &$visited = [], int $distance = 0) : bool{ $index = World::blockHash($pos->x, $pos->y, $pos->z); if(isset($visited[$index])){ return false; } $visited[$index] = true; $block = $this->position->getWorld()->getBlock($pos); if($block instanceof Wood){ //type doesn't matter return true; } if($block instanceof Leaves && $distance <= 4){ foreach(Facing::ALL as $side){ if($this->findLog($pos->getSide($side), $visited, $distance + 1)){ return true; } } } return false; } public function onNearbyBlockChange() : void{ if(!$this->noDecay && !$this->checkDecay){ $this->checkDecay = true; $this->position->getWorld()->setBlock($this->position, $this, false); } } public function ticksRandomly() : bool{ return true; } public function onRandomTick() : void{ if(!$this->noDecay && $this->checkDecay){ $ev = new LeavesDecayEvent($this); $ev->call(); if($ev->isCancelled() || $this->findLog($this->position)){ $this->checkDecay = false; $this->position->getWorld()->setBlock($this->position, $this, false); }else{ $this->position->getWorld()->useBreakOn($this->position); } } } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ $this->noDecay = true; //artificial leaves don't decay return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } public function getDropsForCompatibleTool(Item $item) : array{ if(($item->getBlockToolType() & BlockToolType::SHEARS) !== 0){ return parent::getDropsForCompatibleTool($item); } $drops = []; if(mt_rand(1, 20) === 1){ //Saplings $drops[] = (match($this->treeType){ TreeType::ACACIA() => VanillaBlocks::ACACIA_SAPLING(), TreeType::BIRCH() => VanillaBlocks::BIRCH_SAPLING(), TreeType::DARK_OAK() => VanillaBlocks::DARK_OAK_SAPLING(), TreeType::JUNGLE() => VanillaBlocks::JUNGLE_SAPLING(), TreeType::OAK() => VanillaBlocks::OAK_SAPLING(), TreeType::SPRUCE() => VanillaBlocks::SPRUCE_SAPLING(), default => throw new AssumptionFailedError("Unreachable") })->asItem(); } if(($this->treeType->equals(TreeType::OAK()) || $this->treeType->equals(TreeType::DARK_OAK())) && mt_rand(1, 200) === 1){ //Apples $drops[] = VanillaItems::APPLE(); } if(mt_rand(1, 50) === 1){ $drops[] = VanillaItems::STICK()->setCount(mt_rand(1, 2)); } return $drops; } public function isAffectedBySilkTouch() : bool{ return true; } public function getFlameEncouragement() : int{ return 30; } public function getFlammability() : int{ return 60; } public function getSupportType(int $facing) : SupportType{ return SupportType::NONE(); } }