potionType = $potionType; parent::__construct($location, $shootingEntity, $nbt); } public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); $nbt->setShort("PotionId", PotionTypeIdMap::getInstance()->toId($this->getPotionType())); return $nbt; } public function getResultDamage() : int{ return -1; //no damage } protected function onHit(ProjectileHitEvent $event) : void{ $effects = $this->getPotionEffects(); $hasEffects = true; if(count($effects) === 0){ $particle = new PotionSplashParticle(PotionSplashParticle::DEFAULT_COLOR()); $hasEffects = false; }else{ $colors = []; foreach($effects as $effect){ $level = $effect->getEffectLevel(); for($j = 0; $j < $level; ++$j){ $colors[] = $effect->getColor(); } } $particle = new PotionSplashParticle(Color::mix(...$colors)); } $this->getWorld()->addParticle($this->location, $particle); $this->broadcastSound(new PotionSplashSound()); if($hasEffects){ if(!$this->willLinger()){ foreach($this->getWorld()->getCollidingEntities($this->boundingBox->expandedCopy(4.125, 2.125, 4.125), $this) as $entity){ if($entity instanceof Living){ $distanceSquared = $entity->getEyePos()->distanceSquared($this->location); if($distanceSquared > 16){ //4 blocks continue; } $distanceMultiplier = 1 - (sqrt($distanceSquared) / 4); if($event instanceof ProjectileHitEntityEvent && $entity === $event->getEntityHit()){ $distanceMultiplier = 1.0; } foreach($this->getPotionEffects() as $effect){ //getPotionEffects() is used to get COPIES to avoid accidentally modifying the same effect instance already applied to another entity if(!($effect->getType() instanceof InstantEffect)){ $newDuration = (int) round($effect->getDuration() * 0.75 * $distanceMultiplier); if($newDuration < 20){ continue; } $effect->setDuration($newDuration); $entity->getEffects()->add($effect); }else{ $effect->getType()->applyEffect($entity, $effect, $distanceMultiplier, $this); } } } } }else{ //TODO: lingering potions } }elseif($event instanceof ProjectileHitBlockEvent && $this->getPotionType()->equals(PotionType::WATER())){ $blockIn = $event->getBlockHit()->getSide($event->getRayTraceResult()->getHitFace()); if($blockIn->getId() === BlockLegacyIds::FIRE){ $this->getWorld()->setBlock($blockIn->getPosition(), VanillaBlocks::AIR()); } foreach($blockIn->getHorizontalSides() as $horizontalSide){ if($horizontalSide->getId() === BlockLegacyIds::FIRE){ $this->getWorld()->setBlock($horizontalSide->getPosition(), VanillaBlocks::AIR()); } } } } /** * Returns the meta value of the potion item that this splash potion corresponds to. This decides what effects will be applied to the entity when it collides with its target. */ public function getPotionType() : PotionType{ return $this->potionType; } public function setPotionType(PotionType $type) : void{ $this->potionType = $type; $this->networkPropertiesDirty = true; } /** * Returns whether this splash potion will create an area-effect cloud when it lands. */ public function willLinger() : bool{ return $this->linger; } /** * Sets whether this splash potion will create an area-effect-cloud when it lands. */ public function setLinger(bool $value = true) : void{ $this->linger = $value; $this->networkPropertiesDirty = true; } /** * @return EffectInstance[] */ public function getPotionEffects() : array{ return $this->potionType->getEffects(); } protected function syncNetworkData(EntityMetadataCollection $properties) : void{ parent::syncNetworkData($properties); $properties->setShort(EntityMetadataProperties::POTION_AUX_VALUE, PotionTypeIdMap::getInstance()->toId($this->potionType)); $properties->setGenericFlag(EntityMetadataFlags::LINGER, $this->linger); } }