PocketMine-MP 5.21.1 git-2ff647079265e7c600203af4fd902b15e99d49a4
Leaves.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\block;
25
27use pocketmine\block\utils\LeavesType;
28use pocketmine\block\utils\SupportType;
38use function mt_rand;
39
40class Leaves extends Transparent{
41 private const MAX_LOG_DISTANCE = 4;
42
43 protected LeavesType $leavesType; //immutable for now
44 protected bool $noDecay = false;
45 protected bool $checkDecay = false;
46
47 public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, LeavesType $leavesType){
48 parent::__construct($idInfo, $name, $typeInfo);
49 $this->leavesType = $leavesType;
50 }
51
52 protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
53 $w->bool($this->noDecay);
54 $w->bool($this->checkDecay);
55 }
56
57 public function getLeavesType() : LeavesType{ return $this->leavesType; }
58
59 public function isNoDecay() : bool{ return $this->noDecay; }
60
62 public function setNoDecay(bool $noDecay) : self{
63 $this->noDecay = $noDecay;
64 return $this;
65 }
66
67 public function isCheckDecay() : bool{ return $this->checkDecay; }
68
70 public function setCheckDecay(bool $checkDecay) : self{
71 $this->checkDecay = $checkDecay;
72 return $this;
73 }
74
75 public function blocksDirectSkyLight() : bool{
76 return true;
77 }
78
84 protected function findLog(Vector3 $pos, array &$visited = [], int $distance = 0) : bool{
85 $index = World::blockHash($pos->x, $pos->y, $pos->z);
86 if(isset($visited[$index])){
87 return false;
88 }
89 $visited[$index] = true;
90
91 $block = $this->position->getWorld()->getBlock($pos);
92 if($block instanceof Wood){ //type doesn't matter
93 return true;
94 }
95
96 if($block instanceof Leaves && $distance <= self::MAX_LOG_DISTANCE){
97 foreach(Facing::ALL as $side){
98 if($this->findLog($pos->getSide($side), $visited, $distance + 1)){
99 return true;
100 }
101 }
102 }
103
104 return false;
105 }
106
107 public function onNearbyBlockChange() : void{
108 if(!$this->noDecay && !$this->checkDecay){
109 $this->checkDecay = true;
110 $this->position->getWorld()->setBlock($this->position, $this, false);
111 }
112 }
113
114 public function ticksRandomly() : bool{
115 return !$this->noDecay && $this->checkDecay;
116 }
117
118 public function onRandomTick() : void{
119 if(!$this->noDecay && $this->checkDecay){
120 $cancelled = false;
121 if(LeavesDecayEvent::hasHandlers()){
122 $ev = new LeavesDecayEvent($this);
123 $ev->call();
124 $cancelled = $ev->isCancelled();
125 }
126
127 $world = $this->position->getWorld();
128 if($cancelled || $this->findLog($this->position)){
129 $this->checkDecay = false;
130 $world->setBlock($this->position, $this, false);
131 }else{
132 $world->useBreakOn($this->position);
133 }
134 }
135 }
136
137 public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
138 $this->noDecay = true; //artificial leaves don't decay
139 return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
140 }
141
142 public function getDropsForCompatibleTool(Item $item) : array{
143 if(($item->getBlockToolType() & BlockToolType::SHEARS) !== 0){
144 return parent::getDropsForCompatibleTool($item);
145 }
146
147 $drops = [];
148 if(FortuneDropHelper::bonusChanceDivisor($item, 20, 4)){ //Saplings
149 // TODO: according to the wiki, the jungle saplings have a different drop rate
150 $sapling = (match($this->leavesType){
151 LeavesType::ACACIA => VanillaBlocks::ACACIA_SAPLING(),
152 LeavesType::BIRCH => VanillaBlocks::BIRCH_SAPLING(),
153 LeavesType::DARK_OAK => VanillaBlocks::DARK_OAK_SAPLING(),
154 LeavesType::JUNGLE => VanillaBlocks::JUNGLE_SAPLING(),
155 LeavesType::OAK => VanillaBlocks::OAK_SAPLING(),
156 LeavesType::SPRUCE => VanillaBlocks::SPRUCE_SAPLING(),
157 LeavesType::MANGROVE, //TODO: mangrove propagule
158 LeavesType::AZALEA, LeavesType::FLOWERING_AZALEA => null, //TODO: azalea
159 LeavesType::CHERRY => null, //TODO: cherry
160 })?->asItem();
161 if($sapling !== null){
162 $drops[] = $sapling;
163 }
164 }
165 if(
166 ($this->leavesType === LeavesType::OAK || $this->leavesType === LeavesType::DARK_OAK) &&
167 FortuneDropHelper::bonusChanceDivisor($item, 200, 20)
168 ){ //Apples
169 $drops[] = VanillaItems::APPLE();
170 }
171 if(FortuneDropHelper::bonusChanceDivisor($item, 50, 5)){
172 $drops[] = VanillaItems::STICK()->setCount(mt_rand(1, 2));
173 }
174
175 return $drops;
176 }
177
178 public function isAffectedBySilkTouch() : bool{
179 return true;
180 }
181
182 public function getFlameEncouragement() : int{
183 return 30;
184 }
185
186 public function getFlammability() : int{
187 return 60;
188 }
189
190 public function getSupportType(int $facing) : SupportType{
191 return SupportType::NONE;
192 }
193}
findLog(Vector3 $pos, array &$visited=[], int $distance=0)
Definition: Leaves.php:84
setNoDecay(bool $noDecay)
Definition: Leaves.php:62
describeBlockOnlyState(RuntimeDataDescriber $w)
Definition: Leaves.php:52
setCheckDecay(bool $checkDecay)
Definition: Leaves.php:70
place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player=null)
Definition: Leaves.php:137
getDropsForCompatibleTool(Item $item)
Definition: Leaves.php:142
getSupportType(int $facing)
Definition: Leaves.php:190
getSide(int $side, int $step=1)
Definition: Vector3.php:120
getBlock(Vector3 $pos, bool $cached=true, bool $addToCache=true)
Definition: World.php:1870