22declare(strict_types=1);
24namespace pocketmine\entity\projectile;
53 public const TAG_POTION_ID =
"PotionId";
55 public static function getNetworkTypeId() :
string{
return EntityIds::SPLASH_POTION; }
57 protected bool $linger =
false;
58 protected PotionType $potionType;
60 public function __construct(
Location $location, ?
Entity $shootingEntity, PotionType $potionType, ?
CompoundTag $nbt =
null){
61 $this->potionType = $potionType;
62 parent::__construct($location, $shootingEntity, $nbt);
68 $nbt = parent::saveNBT();
69 $nbt->
setShort(self::TAG_POTION_ID, PotionTypeIdMap::getInstance()->toId($this->getPotionType()));
79 $effects = $this->getPotionEffects();
82 if(count($effects) === 0){
87 foreach($effects as $effect){
88 $level = $effect->getEffectLevel();
89 for($j = 0; $j < $level; ++$j){
90 $colors[] = $effect->getColor();
93 $particle =
new PotionSplashParticle(Color::mix(...$colors));
96 $this->getWorld()->addParticle($this->location, $particle);
97 $this->broadcastSound(
new PotionSplashSound());
100 if(!$this->willLinger()){
101 foreach($this->getWorld()->getCollidingEntities($this->boundingBox->expandedCopy(4.125, 2.125, 4.125), $this) as $entity){
102 if($entity instanceof Living){
103 $distanceSquared = $entity->getEyePos()->distanceSquared($this->location);
104 if($distanceSquared > 16){
108 $distanceMultiplier = 1 - (sqrt($distanceSquared) / 4);
109 if($event instanceof ProjectileHitEntityEvent && $entity === $event->getEntityHit()){
110 $distanceMultiplier = 1.0;
113 foreach($this->getPotionEffects() as $effect){
116 if(!($effect->getType() instanceof InstantEffect)){
117 $newDuration = (int) round($effect->getDuration() * 0.75 * $distanceMultiplier);
118 if($newDuration < 20){
121 $effect->setDuration($newDuration);
122 $entity->getEffects()->add($effect);
124 $effect->getType()->applyEffect($entity, $effect, $distanceMultiplier, $this);
132 }elseif($event instanceof ProjectileHitBlockEvent && $this->getPotionType() === PotionType::WATER){
133 $blockIn = $event->getBlockHit()->getSide($event->
getRayTraceResult()->getHitFace());
135 if($blockIn->hasTypeTag(BlockTypeTags::FIRE)){
136 $this->getWorld()->setBlock($blockIn->getPosition(), VanillaBlocks::AIR());
138 foreach($blockIn->getHorizontalSides() as $horizontalSide){
139 if($horizontalSide->hasTypeTag(BlockTypeTags::FIRE)){
140 $this->getWorld()->setBlock($horizontalSide->getPosition(), VanillaBlocks::AIR());
150 return $this->potionType;
153 public function setPotionType(PotionType $type) : void{
154 $this->potionType = $type;
155 $this->networkPropertiesDirty =
true;
162 return $this->linger;
169 $this->linger = $value;
170 $this->networkPropertiesDirty =
true;
177 return $this->potionType->getEffects();
181 parent::syncNetworkData($properties);
183 $properties->setShort(EntityMetadataProperties::POTION_AUX_VALUE, PotionTypeIdMap::getInstance()->toId($this->potionType));
184 $properties->setGenericFlag(EntityMetadataFlags::LINGER, $this->linger);
onHit(ProjectileHitEvent $event)
setLinger(bool $value=true)
setShort(string $name, int $value)