package net.minecraft.server; import com.google.common.base.Predicate; import com.koloboke.collect.map.hash.HashObjDoubleMaps; import java.util.Iterator; import java.util.List; import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; // CraftBukkit start import java.util.HashMap; import java.util.Map; import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.entity.LivingEntity; // CraftBukkit end public class EntityPotion extends EntityProjectile { private static final DataWatcherObject<ItemStack> e = DataWatcher.a(EntityPotion.class, DataWatcherRegistry.f); private static final Logger f = LogManager.getLogger(); public static final Predicate<EntityLiving> d = new Predicate() { public boolean a(@Nullable EntityLiving entityliving) { return EntityPotion.c(entityliving); } @Override public boolean apply(@Nullable Object object) { return this.a((EntityLiving) object); } }; public EntityPotion(World world) { super(world); } public EntityPotion(World world, EntityLiving entityliving, ItemStack itemstack) { super(world, entityliving); this.setItem(itemstack); } public EntityPotion(World world, double d0, double d1, double d2, ItemStack itemstack) { super(world, d0, d1, d2); if (!itemstack.isEmpty()) { this.setItem(itemstack); } } @Override protected void i() { this.getDataWatcher().register(EntityPotion.e, ItemStack.a); } public ItemStack getItem() { ItemStack itemstack = this.getDataWatcher().get(EntityPotion.e); if (itemstack.getItem() != Items.SPLASH_POTION && itemstack.getItem() != Items.LINGERING_POTION) { if (this.world != null) { EntityPotion.f.error("ThrownPotion entity {} has no item?!", new Object[] { Integer.valueOf(this.getId())}); } return new ItemStack(Items.SPLASH_POTION); } else { return itemstack; } } public void setItem(ItemStack itemstack) { this.getDataWatcher().set(EntityPotion.e, itemstack); this.getDataWatcher().markDirty(EntityPotion.e); } @Override protected float j() { return 0.05F; } @Override protected void a(MovingObjectPosition movingobjectposition) { if (!this.world.isClientSide) { ItemStack itemstack = this.getItem(); PotionRegistry potionregistry = PotionUtil.d(itemstack); List list = PotionUtil.getEffects(itemstack); boolean flag = potionregistry == Potions.b && list.isEmpty(); if (movingobjectposition.type == MovingObjectPosition.EnumMovingObjectType.BLOCK && flag) { BlockPosition blockposition = movingobjectposition.a().shift(movingobjectposition.direction); this.a(blockposition); Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); while (iterator.hasNext()) { EnumDirection enumdirection = (EnumDirection) iterator.next(); this.a(blockposition.shift(enumdirection)); } } if (flag) { this.n(); } else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply if (this.isLingering()) { this.a(itemstack, potionregistry); } else { this.a(movingobjectposition, list); } } int i = potionregistry.c() ? 2007 : 2002; this.world.triggerEffect(i, new BlockPosition(this), PotionUtil.c(itemstack)); this.die(); } } private void n() { AxisAlignedBB axisalignedbb = this.getBoundingBox().grow(4.0D, 2.0D, 4.0D); List list = this.world.a(EntityLiving.class, axisalignedbb, EntityPotion.d); if (!list.isEmpty()) { Iterator iterator = list.iterator(); while (iterator.hasNext()) { EntityLiving entityliving = (EntityLiving) iterator.next(); double d0 = this.h(entityliving); if (d0 < 16.0D && c(entityliving)) { entityliving.damageEntity(DamageSource.DROWN, 1.0F); } } } } private void a(MovingObjectPosition movingobjectposition, List<MobEffect> list) { AxisAlignedBB axisalignedbb = this.getBoundingBox().grow(4.0D, 2.0D, 4.0D); List list1 = this.world.a(EntityLiving.class, axisalignedbb); Map<LivingEntity, Double> affected = HashObjDoubleMaps.newMutableMap(); // CraftBukkit if (!list1.isEmpty()) { Iterator iterator = list1.iterator(); while (iterator.hasNext()) { EntityLiving entityliving = (EntityLiving) iterator.next(); if (entityliving.cJ()) { double d0 = this.h(entityliving); if (d0 < 16.0D) { double d1 = 1.0D - Math.sqrt(d0) / 4.0D; if (entityliving == movingobjectposition.entity) { d1 = 1.0D; } // CraftBukkit start affected.put((LivingEntity) entityliving.getBukkitEntity(), d1); } } } } org.bukkit.event.entity.PotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPotionSplashEvent(this, affected); if (!event.isCancelled() && list != null && !list.isEmpty()) { // do not process effects if there are no effects to process for (LivingEntity victim : event.getAffectedEntities()) { if (!(victim instanceof CraftLivingEntity)) { continue; } EntityLiving entityliving = ((CraftLivingEntity) victim).getHandle(); double d1 = event.getIntensity(victim); // CraftBukkit end Iterator iterator1 = list.iterator(); while (iterator1.hasNext()) { MobEffect mobeffect = (MobEffect) iterator1.next(); MobEffectList mobeffectlist = mobeffect.getMobEffect(); // CraftBukkit start - Abide by PVP settings - for players only! if (!this.world.pvpMode && this.getShooter() instanceof EntityPlayer && entityliving instanceof EntityPlayer && entityliving != this.getShooter()) { int i = MobEffectList.getId(mobeffectlist); // Block SLOWER_MOVEMENT, SLOWER_DIG, HARM, BLINDNESS, HUNGER, WEAKNESS and POISON potions if (i == 2 || i == 4 || i == 7 || i == 15 || i == 17 || i == 18 || i == 19) { continue; } } // CraftBukkit end if (mobeffectlist.isInstant()) { mobeffectlist.applyInstantEffect(this, this.getShooter(), entityliving, mobeffect.getAmplifier(), d1); } else { int i = (int) (d1 * mobeffect.getDuration() + 0.5D); if (i > 20) { entityliving.addEffect(new MobEffect(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isShowParticles())); } } } } } } private void a(ItemStack itemstack, PotionRegistry potionregistry) { EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.world, this.locX, this.locY, this.locZ); entityareaeffectcloud.projectileSource = this.projectileSource; // CraftBukkit entityareaeffectcloud.setSource(this.getShooter()); entityareaeffectcloud.setRadius(3.0F); entityareaeffectcloud.setRadiusOnUse(-0.5F); entityareaeffectcloud.setWaitTime(10); entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / entityareaeffectcloud.getDuration()); entityareaeffectcloud.a(potionregistry); Iterator iterator = PotionUtil.b(itemstack).iterator(); while (iterator.hasNext()) { MobEffect mobeffect = (MobEffect) iterator.next(); entityareaeffectcloud.a(new MobEffect(mobeffect)); } NBTTagCompound nbttagcompound = itemstack.getTag(); if (nbttagcompound != null && nbttagcompound.hasKeyOfType("CustomPotionColor", 99)) { entityareaeffectcloud.setColor(nbttagcompound.getInt("CustomPotionColor")); } // CraftBukkit start org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, entityareaeffectcloud); if (!(event.isCancelled() || entityareaeffectcloud.dead)) { this.world.addEntity(entityareaeffectcloud); } else { entityareaeffectcloud.dead = true; } // CraftBukkit end } public boolean isLingering() { return this.getItem().getItem() == Items.LINGERING_POTION; } private void a(BlockPosition blockposition) { if (this.world.getType(blockposition).getBlock() == Blocks.FIRE) { this.world.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 2); } } public static void a(DataConverterManager dataconvertermanager) { EntityProjectile.a(dataconvertermanager, "ThrownPotion"); dataconvertermanager.a(DataConverterTypes.ENTITY, (new DataInspectorItem(EntityPotion.class, new String[] { "Potion"}))); } @Override public void a(NBTTagCompound nbttagcompound) { super.a(nbttagcompound); ItemStack itemstack = new ItemStack(nbttagcompound.getCompound("Potion")); if (itemstack.isEmpty()) { this.die(); } else { this.setItem(itemstack); } } @Override public void b(NBTTagCompound nbttagcompound) { super.b(nbttagcompound); ItemStack itemstack = this.getItem(); if (!itemstack.isEmpty()) { nbttagcompound.set("Potion", itemstack.save(new NBTTagCompound())); } } private static boolean c(EntityLiving entityliving) { return entityliving instanceof EntityEnderman || entityliving instanceof EntityBlaze; } }