PocketMine-MP 5.14.2 git-50e2c469a547a16a23b2dc691e70a51d34e29395
Bow.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\item;
25
27use pocketmine\entity\projectile\Arrow as ArrowEntity;
34use function intdiv;
35use function min;
36
37class Bow extends Tool implements Releasable{
38
39 public function getFuelTime() : int{
40 return 200;
41 }
42
43 public function getMaxDurability() : int{
44 return 385;
45 }
46
47 public function onReleaseUsing(Player $player, array &$returnedItems) : ItemUseResult{
48 $arrow = VanillaItems::ARROW();
49 $inventory = match(true){
50 $player->getOffHandInventory()->contains($arrow) => $player->getOffHandInventory(),
51 $player->getInventory()->contains($arrow) => $player->getInventory(),
52 default => null
53 };
54
55 if($player->hasFiniteResources() && $inventory === null){
56 return ItemUseResult::FAIL;
57 }
58
59 $location = $player->getLocation();
60
61 $diff = $player->getItemUseDuration();
62 $p = $diff / 20;
63 $baseForce = min((($p ** 2) + $p * 2) / 3, 1);
64
65 $entity = new ArrowEntity(Location::fromObject(
66 $player->getEyePos(),
67 $player->getWorld(),
68 ($location->yaw > 180 ? 360 : 0) - $location->yaw,
69 -$location->pitch
70 ), $player, $baseForce >= 1);
71 $entity->setMotion($player->getDirectionVector());
72
73 $infinity = $this->hasEnchantment(VanillaEnchantments::INFINITY());
74 if($infinity){
75 $entity->setPickupMode(ArrowEntity::PICKUP_CREATIVE);
76 }
77 if(($punchLevel = $this->getEnchantmentLevel(VanillaEnchantments::PUNCH())) > 0){
78 $entity->setPunchKnockback($punchLevel);
79 }
80 if(($powerLevel = $this->getEnchantmentLevel(VanillaEnchantments::POWER())) > 0){
81 $entity->setBaseDamage($entity->getBaseDamage() + (($powerLevel + 1) / 2));
82 }
83 if($this->hasEnchantment(VanillaEnchantments::FLAME())){
84 $entity->setOnFire(intdiv($entity->getFireTicks(), 20) + 100);
85 }
86 $ev = new EntityShootBowEvent($player, $this, $entity, $baseForce * 3);
87
88 if($baseForce < 0.1 || $diff < 5 || $player->isSpectator()){
89 $ev->cancel();
90 }
91
92 $ev->call();
93
94 $entity = $ev->getProjectile(); //This might have been changed by plugins
95
96 if($ev->isCancelled()){
97 $entity->flagForDespawn();
98 return ItemUseResult::FAIL;
99 }
100
101 $entity->setMotion($entity->getMotion()->multiply($ev->getForce()));
102
103 if($entity instanceof Projectile){
104 $projectileEv = new ProjectileLaunchEvent($entity);
105 $projectileEv->call();
106 if($projectileEv->isCancelled()){
107 $ev->getProjectile()->flagForDespawn();
108 return ItemUseResult::FAIL;
109 }
110
111 $ev->getProjectile()->spawnToAll();
112 $location->getWorld()->addSound($location, new BowShootSound());
113 }else{
114 $entity->spawnToAll();
115 }
116
117 if($player->hasFiniteResources()){
118 if(!$infinity){ //TODO: tipped arrows are still consumed when Infinity is applied
119 $inventory?->removeItem($arrow);
120 }
121 $this->applyDamage(1);
122 }
123
124 return ItemUseResult::SUCCESS;
125 }
126
127 public function canStartUsingItem(Player $player) : bool{
128 return !$player->hasFiniteResources() || $player->getOffHandInventory()->contains($arrow = VanillaItems::ARROW()) || $player->getInventory()->contains($arrow);
129 }
130}
onReleaseUsing(Player $player, array &$returnedItems)
Definition: Bow.php:47
getEnchantmentLevel(Enchantment $enchantment)