PocketMine-MP 5.23.3 git-f7687af337d001ddbcc47b8e773f014a33faa662
Loading...
Searching...
No Matches
Campfire.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\tile\Campfire as TileCampfire;
28use pocketmine\block\utils\HorizontalFacingTrait;
29use pocketmine\block\utils\LightableTrait;
30use pocketmine\block\utils\SupportType;
32use pocketmine\crafting\FurnaceType;
58use function count;
59use function min;
60use function mt_rand;
61
62class Campfire extends Transparent{
63 use HorizontalFacingTrait{
64 HorizontalFacingTrait::describeBlockOnlyState as encodeFacingState;
65 }
66 use LightableTrait{
67 LightableTrait::describeBlockOnlyState as encodeLitState;
68 }
69
70 private const UPDATE_INTERVAL_TICKS = 10;
71
77
82 protected array $cookingTimes = [];
83
84 protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
85 $this->encodeFacingState($w);
86 $this->encodeLitState($w);
87 }
88
89 public function readStateFromWorld() : Block{
90 parent::readStateFromWorld();
91 $tile = $this->position->getWorld()->getTile($this->position);
92 if($tile instanceof TileCampfire){
93 $this->inventory = $tile->getInventory();
94 $this->cookingTimes = $tile->getCookingTimes();
95 }else{
96 $this->inventory = new CampfireInventory($this->position);
97 }
98
99 return $this;
100 }
101
102 public function writeStateToWorld() : void{
103 parent::writeStateToWorld();
104 $tile = $this->position->getWorld()->getTile($this->position);
105 if($tile instanceof TileCampfire){
106 $tile->setCookingTimes($this->cookingTimes);
107 }
108 }
109
110 public function hasEntityCollision() : bool{
111 return true;
112 }
113
114 public function getLightLevel() : int{
115 return $this->lit ? 15 : 0;
116 }
117
118 public function isAffectedBySilkTouch() : bool{
119 return true;
120 }
121
122 public function getDropsForCompatibleTool(Item $item) : array{
123 return [
124 VanillaItems::CHARCOAL()->setCount(2)
125 ];
126 }
127
128 public function getSupportType(int $facing) : SupportType{
129 return SupportType::NONE;
130 }
131
132 protected function recalculateCollisionBoxes() : array{
133 return [AxisAlignedBB::one()->trim(Facing::UP, 9 / 16)];
134 }
135
140 public function getInventory() : CampfireInventory{
141 return $this->inventory;
142 }
143
144 protected function getFurnaceType() : FurnaceType{
145 return FurnaceType::CAMPFIRE;
146 }
147
148 protected function getEntityCollisionDamage() : int{
149 return 1;
150 }
151
155 public function setCookingTime(int $slot, int $time) : void{
156 if($slot < 0 || $slot > 3){
157 throw new \InvalidArgumentException("Slot must be in range 0-3");
158 }
159 if($time < 0 || $time > $this->getFurnaceType()->getCookDurationTicks()){
160 throw new \InvalidArgumentException("CookingTime must be in range 0-" . $this->getFurnaceType()->getCookDurationTicks());
161 }
162 $this->cookingTimes[$slot] = $time;
163 }
164
168 public function getCookingTime(int $slot) : int{
169 return $this->cookingTimes[$slot] ?? 0;
170 }
171
172 public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
173 if($this->getSide(Facing::DOWN) instanceof Campfire){
174 return false;
175 }
176 if($player !== null){
177 $this->facing = $player->getHorizontalFacing();
178 }
179 $this->lit = true;
180 return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
181 }
182
183 public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
184 if(!$this->lit){
185 if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE){
186 $item->pop();
187 $this->ignite();
188 $this->position->getWorld()->addSound($this->position, new BlazeShootSound());
189 return true;
190 }elseif($item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
191 if($item instanceof Durable){
192 $item->applyDamage(1);
193 }
194 $this->ignite();
195 return true;
196 }
197 }elseif($item instanceof Shovel){
198 $item->applyDamage(1);
199 $this->extinguish();
200 return true;
201 }
202
203 if($this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($this->getFurnaceType())->match($item) !== null){
204 $ingredient = clone $item;
205 $ingredient->setCount(1);
206 if(count($this->inventory->addItem($ingredient)) === 0){
207 $item->pop();
208 $this->position->getWorld()->addSound($this->position, new ItemFrameAddItemSound());
209 return true;
210 }
211 }
212 return false;
213 }
214
215 public function onNearbyBlockChange() : void{
216 if($this->lit && $this->getSide(Facing::UP)->getTypeId() === BlockTypeIds::WATER){
217 $this->extinguish();
218 //TODO: Waterlogging
219 }
220 }
221
222 public function onEntityInside(Entity $entity) : bool{
223 if(!$this->lit){
224 if($entity->isOnFire()){
225 $this->ignite();
226 return false;
227 }
228 }elseif($entity instanceof Living){
229 $entity->attack(new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, $this->getEntityCollisionDamage()));
230 }
231 return true;
232 }
233
234 public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
235 if($this->lit && $projectile instanceof SplashPotion && $projectile->getPotionType() === PotionType::WATER){
236 $this->extinguish();
237 }
238 }
239
240 public function onScheduledUpdate() : void{
241 if($this->lit){
242 $items = $this->inventory->getContents();
243 $furnaceType = $this->getFurnaceType();
244 $maxCookDuration = $furnaceType->getCookDurationTicks();
245 foreach($items as $slot => $item){
246 $this->setCookingTime($slot, min($maxCookDuration, $this->getCookingTime($slot) + self::UPDATE_INTERVAL_TICKS));
247 if($this->getCookingTime($slot) >= $maxCookDuration){
248 $result =
249 ($recipe = $this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($furnaceType)->match($item)) instanceof FurnaceRecipe ?
250 $recipe->getResult() :
251 VanillaItems::AIR();
252
253 $ev = new CampfireCookEvent($this, $slot, $item, $result);
254 $ev->call();
255
256 if ($ev->isCancelled()){
257 continue;
258 }
259
260 $this->inventory->setItem($slot, VanillaItems::AIR());
261 $this->setCookingTime($slot, 0);
262 $this->position->getWorld()->dropItem($this->position->add(0.5, 1, 0.5), $ev->getResult());
263 }
264 }
265 if(count($items) > 0){
266 $this->position->getWorld()->setBlock($this->position, $this);
267 }
268 if(mt_rand(1, 6) === 1){
269 $this->position->getWorld()->addSound($this->position, $furnaceType->getCookSound());
270 }
271 $this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
272 }
273 }
274
275 private function extinguish() : void{
276 $this->position->getWorld()->addSound($this->position, new FireExtinguishSound());
277 $this->position->getWorld()->setBlock($this->position, $this->setLit(false));
278 }
279
280 private function ignite() : void{
281 $this->position->getWorld()->addSound($this->position, new FlintSteelSound());
282 $this->position->getWorld()->setBlock($this->position, $this->setLit(true));
283 $this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
284 }
285}
place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player=null)
Definition Campfire.php:172
describeBlockOnlyState(RuntimeDataDescriber $w)
Definition Campfire.php:84
onProjectileHit(Projectile $projectile, RayTraceResult $hitResult)
Definition Campfire.php:234
getSupportType(int $facing)
Definition Campfire.php:128
setCookingTime(int $slot, int $time)
Definition Campfire.php:155
getDropsForCompatibleTool(Item $item)
Definition Campfire.php:122
onEntityInside(Entity $entity)
Definition Campfire.php:222
CampfireInventory $inventory
Definition Campfire.php:76
onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player=null, array &$returnedItems=[])
Definition Campfire.php:183