PocketMine-MP 5.15.1 git-5ef247620a7c6301a849b54e5ef1009217729fc8
SmallDripleaf.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
26use pocketmine\block\utils\HorizontalFacingTrait;
27use pocketmine\block\utils\SupportType;
37use function mt_rand;
38
40 use HorizontalFacingTrait;
41
42 protected bool $top = false;
43
44 public function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
45 $w->horizontalFacing($this->facing);
46 $w->bool($this->top);
47 }
48
49 public function isTop() : bool{
50 return $this->top;
51 }
52
54 public function setTop(bool $top) : self{
55 $this->top = $top;
56 return $this;
57 }
58
59 private function canBeSupportedBy(Block $block) : bool{
60 //TODO: Moss
61 //TODO: Small Dripleaf also can be placed on dirt, coarse dirt, farmland, grass blocks,
62 // podzol, rooted dirt, mycelium, and mud if these blocks are underwater (needs waterlogging)
63 return $block->getTypeId() === BlockTypeIds::CLAY;
64 }
65
66 public function onNearbyBlockChange() : void{
67 if(!$this->top && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
68 $this->position->getWorld()->useBreakOn($this->position);
69 return;
70 }
71 $face = $this->top ? Facing::DOWN : Facing::UP;
72 if(!$this->getSide($face)->hasSameTypeId($this)){
73 $this->position->getWorld()->useBreakOn($this->position);
74 }
75 }
76
77 public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
78 $block = $blockReplace->getSide(Facing::UP);
79 if($block->getTypeId() !== BlockTypeIds::AIR || !$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
80 return false;
81 }
82 if($player !== null){
83 $this->facing = Facing::opposite($player->getHorizontalFacing());
84 }
85
86 $tx->addBlock($block->position, VanillaBlocks::SMALL_DRIPLEAF()
87 ->setFacing($this->facing)
88 ->setTop(true)
89 );
90 return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
91 }
92
93 public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
94 if($item instanceof Fertilizer && $this->grow($player)){
95 $item->pop();
96 return true;
97 }
98 return false;
99 }
100
101 private function canGrowTo(Position $pos) : bool{
102 $world = $pos->getWorld();
103 if(!$world->isInWorld($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ())){
104 return false;
105 }
106 $block = $world->getBlock($pos);
107 return $block->hasSameTypeId($this) || $block->getTypeId() === BlockTypeIds::AIR;
108 }
109
110 private function grow(?Player $player) : bool{
111 $bottomBlock = $this->top ? $this->getSide(Facing::DOWN) : $this;
112 if(!$this->hasSameTypeId($bottomBlock)){
113 return false;
114 }
115 $world = $this->position->getWorld();
116 $tx = new BlockTransaction($world);
117 $height = mt_rand(2, 5);
118 $grown = 0;
119 for($i = 0; $i < $height; $i++){
120 $pos = $bottomBlock->getSide(Facing::UP, $i)->position;
121 if(!$this->canGrowTo($pos)){
122 break;
123 }
124 $block = ++$grown < $height && $this->canGrowTo($pos->getSide(Facing::UP)) ?
125 VanillaBlocks::BIG_DRIPLEAF_STEM() :
126 VanillaBlocks::BIG_DRIPLEAF_HEAD();
127 $tx->addBlock($pos, $block->setFacing($this->facing));
128 }
129 if($grown > 1){
130 $ev = new StructureGrowEvent($bottomBlock, $tx, $player);
131 $ev->call();
132 if(!$ev->isCancelled()){
133 return $tx->apply();
134 }
135 }
136
137 return false;
138 }
139
140 public function getAffectedBlocks() : array{
141 $other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
142 if($other->hasSameTypeId($this)){
143 return [$this, $other];
144 }
145 return parent::getAffectedBlocks();
146 }
147
148 public function getDropsForCompatibleTool(Item $item) : array{
149 if(!$this->top){
150 return [$this->asItem()];
151 }
152 return [];
153 }
154
155 public function getFlameEncouragement() : int{
156 return 15;
157 }
158
159 public function getFlammability() : int{
160 return 100;
161 }
162
163 public function getSupportType(int $facing) : SupportType{
164 return SupportType::NONE;
165 }
166
167 protected function recalculateCollisionBoxes() : array{
168 return [];
169 }
170}
getSide(int $side, int $step=1)
Definition: Block.php:768
onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player=null, array &$returnedItems=[])
describeBlockOnlyState(RuntimeDataDescriber $w)
place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player=null)
pop(int $count=1)
Definition: Item.php:430
addBlock(Vector3 $pos, Block $state)
getSide(int $side, int $step=1)
Definition: Position.php:87