PocketMine-MP 5.35.1 git-e32e836dad793a3a3c8ddd8927c00e112b1e576a
Loading...
Searching...
No Matches
entity/projectile/Trident.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\entity\projectile;
25
43
44class Trident extends Projectile{
45
46 public const TAG_ITEM = "Trident"; //TAG_Compound
47 protected const TAG_SPAWNED_IN_CREATIVE = "isCreative"; //TAG_Byte
48
49 public function getNetworkTypeId() : string{ return EntityIds::THROWN_TRIDENT; }
50
51 protected Item $item;
52
53 protected float $damage = 8.0;
54
55 protected bool $canCollide = true;
56
57 protected bool $spawnedInCreative = false;
58
59 public function __construct(
60 Location $location,
61 Item $item,
62 ?Entity $shootingEntity,
63 ?CompoundTag $nbt = null
64 ){
65 if($item->isNull()){
66 throw new \InvalidArgumentException("Trident must have a count of at least 1");
67 }
68 $this->item = clone $item;
69 parent::__construct($location, $shootingEntity, $nbt);
70 }
71
72 protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.35, 0.25); }
73
74 protected function getInitialDragMultiplier() : float{ return 0.01; }
75
76 protected function getInitialGravity() : float{ return 0.1; }
77
78 protected function initEntity(CompoundTag $nbt) : void{
79 parent::initEntity($nbt);
80
81 $this->spawnedInCreative = $nbt->getByte(self::TAG_SPAWNED_IN_CREATIVE, 0) === 1;
82 }
83
84 public function saveNBT() : CompoundTag{
85 $nbt = parent::saveNBT();
86 $nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
87 $nbt->setByte(self::TAG_SPAWNED_IN_CREATIVE, $this->spawnedInCreative ? 1 : 0);
88 return $nbt;
89 }
90
91 protected function onFirstUpdate(int $currentTick) : void{
92 $owner = $this->getOwningEntity();
93 $this->spawnedInCreative = $owner instanceof Player && $owner->isCreative();
94
95 parent::onFirstUpdate($currentTick);
96 }
97
98 protected function entityBaseTick(int $tickDiff = 1) : bool{
99 if($this->closed){
100 return false;
101 }
102 //TODO: Loyalty enchantment.
103
104 return parent::entityBaseTick($tickDiff);
105 }
106
107 protected function despawnsOnEntityHit() : bool{
108 return false;
109 }
110
111 protected function onHitEntity(Entity $entityHit, RayTraceResult $hitResult) : void{
112 parent::onHitEntity($entityHit, $hitResult);
113
114 $this->canCollide = false;
115 $this->broadcastSound(new TridentHitEntitySound());
116 $this->setMotion(new Vector3($this->motion->x * -0.01, $this->motion->y * -0.1, $this->motion->z * -0.01));
117 }
118
119 protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
120 parent::onHitBlock($blockHit, $hitResult);
121 $this->canCollide = true;
122 $this->broadcastSound(new TridentHitBlockSound());
123 }
124
125 public function getItem() : Item{
126 return clone $this->item;
127 }
128
129 public function setItem(Item $item) : void{
130 if($item->isNull()){
131 throw new \InvalidArgumentException("Trident must have a count of at least 1");
132 }
133 if($this->item->hasEnchantments() !== $item->hasEnchantments()){
134 $this->networkPropertiesDirty = true;
135 }
136 $this->item = clone $item;
137 }
138
139 public function canCollideWith(Entity $entity) : bool{
140 return $this->canCollide && $entity->getId() !== $this->ownerId && parent::canCollideWith($entity);
141 }
142
143 public function onCollideWithPlayer(Player $player) : void{
144 if($this->blockHit !== null){
145 $this->pickup($player);
146 }
147 }
148
149 private function pickup(Player $player) : void{
150 $shouldDespawn = false;
151
152 $playerInventory = $player->getInventory();
153 $ev = new EntityItemPickupEvent($player, $this, $this->getItem(), $playerInventory);
154 if($player->hasFiniteResources() && !$playerInventory->canAddItem($ev->getItem())){
155 $ev->cancel();
156 }
157 if($this->spawnedInCreative){
158 $ev->cancel();
159 $shouldDespawn = true;
160 }
161
162 $ev->call();
163 if(!$ev->isCancelled()){
164 $ev->getInventory()?->addItem($ev->getItem());
165 $shouldDespawn = true;
166 }
167
168 if($shouldDespawn){
169 //even if the item was not actually picked up, the animation must be displayed.
170 NetworkBroadcastUtils::broadcastEntityEvent(
171 $this->getViewers(),
172 fn(EntityEventBroadcaster $broadcaster, array $recipients) => $broadcaster->onPickUpItem($recipients, $player, $this)
173 );
174 $this->flagForDespawn();
175 }
176 }
177
178 protected function syncNetworkData(EntityMetadataCollection $properties) : void{
179 parent::syncNetworkData($properties);
180
181 $properties->setGenericFlag(EntityMetadataFlags::ENCHANTED, $this->item->hasEnchantments());
182 }
183}
onHitEntity(Entity $entityHit, RayTraceResult $hitResult)
onHitBlock(Block $blockHit, RayTraceResult $hitResult)
setByte(string $name, int $value)
setTag(string $name, Tag $tag)
isCreative(bool $literal=false)
Definition Player.php:1270