package net.minecraft.server; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.Map.Entry; import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; // CraftBukkit start import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.entity.LivingEntity; // CraftBukkit end public class EntityAreaEffectCloud extends Entity { private static final Logger LOGGER = LogManager.getLogger(); private static final DataWatcherObject<Float> c = DataWatcher.a(EntityAreaEffectCloud.class, DataWatcherRegistry.c); private static final DataWatcherObject<Integer> COLOR = DataWatcher.a(EntityAreaEffectCloud.class, DataWatcherRegistry.b); private static final DataWatcherObject<Boolean> e = DataWatcher.a(EntityAreaEffectCloud.class, DataWatcherRegistry.i); private static final DataWatcherObject<ParticleParam> f = DataWatcher.a(EntityAreaEffectCloud.class, DataWatcherRegistry.j); private PotionRegistry potionRegistry; public List<MobEffect> effects; private final Map<Entity, Integer> affectedEntities; private int duration; public int waitTime; public int reapplicationDelay; private boolean hasColor; public int durationOnUse; public float radiusOnUse; public float radiusPerTick; private EntityLiving ax; private UUID ay; public EntityAreaEffectCloud(EntityTypes<? extends EntityAreaEffectCloud> entitytypes, World world) { super(entitytypes, world); this.potionRegistry = Potions.EMPTY; this.effects = Lists.newArrayList(); this.affectedEntities = Maps.newHashMap(); this.duration = 600; this.waitTime = 20; this.reapplicationDelay = 20; this.noclip = true; this.setRadius(3.0F); } public EntityAreaEffectCloud(World world, double d0, double d1, double d2) { this(EntityTypes.AREA_EFFECT_CLOUD, world); this.setPosition(d0, d1, d2); } @Override protected void initDatawatcher() { this.getDataWatcher().register(EntityAreaEffectCloud.COLOR, 0); this.getDataWatcher().register(EntityAreaEffectCloud.c, 0.5F); this.getDataWatcher().register(EntityAreaEffectCloud.e, false); this.getDataWatcher().register(EntityAreaEffectCloud.f, Particles.ENTITY_EFFECT); } public void setRadius(float f) { if (!this.world.isClientSide) { this.getDataWatcher().set(EntityAreaEffectCloud.c, f); } } @Override public void updateSize() { double d0 = this.locX(); double d1 = this.locY(); double d2 = this.locZ(); super.updateSize(); this.setPosition(d0, d1, d2); } public float getRadius() { return (Float) this.getDataWatcher().get(EntityAreaEffectCloud.c); } public void a(PotionRegistry potionregistry) { this.potionRegistry = potionregistry; if (!this.hasColor) { this.z(); } } private void z() { if (this.potionRegistry == Potions.EMPTY && this.effects.isEmpty()) { this.getDataWatcher().set(EntityAreaEffectCloud.COLOR, 0); } else { this.getDataWatcher().set(EntityAreaEffectCloud.COLOR, PotionUtil.a((Collection) PotionUtil.a(this.potionRegistry, (Collection) this.effects))); } } public void addEffect(MobEffect mobeffect) { this.effects.add(mobeffect); if (!this.hasColor) { this.z(); } } // CraftBukkit start accessor methods public void refreshEffects() { if (!this.hasColor) { this.getDataWatcher().set(EntityAreaEffectCloud.COLOR, PotionUtil.a((Collection) PotionUtil.a(this.potionRegistry, (Collection) this.effects))); // PAIL: rename } } public String getType() { return ((MinecraftKey) IRegistry.POTION.getKey(this.potionRegistry)).toString(); } public void setType(String string) { a(IRegistry.POTION.get(new MinecraftKey(string))); } // CraftBukkit end public int getColor() { return (Integer) this.getDataWatcher().get(EntityAreaEffectCloud.COLOR); } public void setColor(int i) { this.hasColor = true; this.getDataWatcher().set(EntityAreaEffectCloud.COLOR, i); } public ParticleParam getParticle() { return (ParticleParam) this.getDataWatcher().get(EntityAreaEffectCloud.f); } public void setParticle(ParticleParam particleparam) { this.getDataWatcher().set(EntityAreaEffectCloud.f, particleparam); } protected void a(boolean flag) { this.getDataWatcher().set(EntityAreaEffectCloud.e, flag); } public boolean l() { return (Boolean) this.getDataWatcher().get(EntityAreaEffectCloud.e); } public int getDuration() { return this.duration; } public void setDuration(int i) { this.duration = i; } @Override public void tick() { super.tick(); boolean flag = this.l(); float f = this.getRadius(); if (this.world.isClientSide) { ParticleParam particleparam = this.getParticle(); float f1; float f2; float f3; int i; int j; int k; if (flag) { if (this.random.nextBoolean()) { for (int l = 0; l < 2; ++l) { float f4 = this.random.nextFloat() * 6.2831855F; f1 = MathHelper.c(this.random.nextFloat()) * 0.2F; f2 = MathHelper.cos(f4) * f1; f3 = MathHelper.sin(f4) * f1; if (particleparam.getParticle() == Particles.ENTITY_EFFECT) { int i1 = this.random.nextBoolean() ? 16777215 : this.getColor(); i = i1 >> 16 & 255; j = i1 >> 8 & 255; k = i1 & 255; this.world.b(particleparam, this.locX() + (double) f2, this.locY(), this.locZ() + (double) f3, (double) ((float) i / 255.0F), (double) ((float) j / 255.0F), (double) ((float) k / 255.0F)); } else { this.world.b(particleparam, this.locX() + (double) f2, this.locY(), this.locZ() + (double) f3, 0.0D, 0.0D, 0.0D); } } } } else { float f5 = 3.1415927F * f * f; for (int j1 = 0; (float) j1 < f5; ++j1) { f1 = this.random.nextFloat() * 6.2831855F; f2 = MathHelper.c(this.random.nextFloat()) * f; f3 = MathHelper.cos(f1) * f2; float f6 = MathHelper.sin(f1) * f2; if (particleparam.getParticle() == Particles.ENTITY_EFFECT) { i = this.getColor(); j = i >> 16 & 255; k = i >> 8 & 255; int k1 = i & 255; this.world.b(particleparam, this.locX() + (double) f3, this.locY(), this.locZ() + (double) f6, (double) ((float) j / 255.0F), (double) ((float) k / 255.0F), (double) ((float) k1 / 255.0F)); } else { this.world.b(particleparam, this.locX() + (double) f3, this.locY(), this.locZ() + (double) f6, (0.5D - this.random.nextDouble()) * 0.15D, 0.009999999776482582D, (0.5D - this.random.nextDouble()) * 0.15D); } } } } else { if (this.ticksLived >= this.waitTime + this.duration) { this.die(); return; } boolean flag1 = this.ticksLived < this.waitTime; if (flag != flag1) { this.a(flag1); } if (flag1) { return; } if (this.radiusPerTick != 0.0F) { f += this.radiusPerTick; if (f < 0.5F) { this.die(); return; } this.setRadius(f); } if (this.ticksLived % 5 == 0) { Iterator iterator = this.affectedEntities.entrySet().iterator(); while (iterator.hasNext()) { Entry<Entity, Integer> entry = (Entry) iterator.next(); if (this.ticksLived >= (Integer) entry.getValue()) { iterator.remove(); } } List<MobEffect> list = Lists.newArrayList(); Iterator iterator1 = this.potionRegistry.a().iterator(); while (iterator1.hasNext()) { MobEffect mobeffect = (MobEffect) iterator1.next(); list.add(new MobEffect(mobeffect.getMobEffect(), mobeffect.getDuration() / 4, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isShowParticles())); } list.addAll(this.effects); if (list.isEmpty()) { this.affectedEntities.clear(); } else { List<EntityLiving> list1 = this.world.a(EntityLiving.class, this.getBoundingBox()); if (!list1.isEmpty()) { Iterator iterator2 = list1.iterator(); List<LivingEntity> entities = new java.util.ArrayList<LivingEntity>(); // CraftBukkit while (iterator2.hasNext()) { EntityLiving entityliving = (EntityLiving) iterator2.next(); if (!this.affectedEntities.containsKey(entityliving) && entityliving.dM()) { double d0 = entityliving.locX() - this.locX(); double d1 = entityliving.locZ() - this.locZ(); double d2 = d0 * d0 + d1 * d1; if (d2 <= (double) (f * f)) { // CraftBukkit start entities.add((LivingEntity) entityliving.getBukkitEntity()); } } } org.bukkit.event.entity.AreaEffectCloudApplyEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callAreaEffectCloudApplyEvent(this, entities); if (!event.isCancelled()) { for (LivingEntity entity : event.getAffectedEntities()) { if (entity instanceof CraftLivingEntity) { EntityLiving entityliving = ((CraftLivingEntity) entity).getHandle(); // CraftBukkit end this.affectedEntities.put(entityliving, this.ticksLived + this.reapplicationDelay); Iterator iterator3 = list.iterator(); while (iterator3.hasNext()) { MobEffect mobeffect1 = (MobEffect) iterator3.next(); if (mobeffect1.getMobEffect().isInstant()) { mobeffect1.getMobEffect().applyInstantEffect(this, this.getSource(), entityliving, mobeffect1.getAmplifier(), 0.5D); } else { entityliving.addEffect(new MobEffect(mobeffect1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit } } if (this.radiusOnUse != 0.0F) { f += this.radiusOnUse; if (f < 0.5F) { this.die(); return; } this.setRadius(f); } if (this.durationOnUse != 0) { this.duration += this.durationOnUse; if (this.duration <= 0) { this.die(); return; } } } } } } } } } } public void setRadiusOnUse(float f) { this.radiusOnUse = f; } public void setRadiusPerTick(float f) { this.radiusPerTick = f; } public void setWaitTime(int i) { this.waitTime = i; } public void setSource(@Nullable EntityLiving entityliving) { this.ax = entityliving; this.ay = entityliving == null ? null : entityliving.getUniqueID(); } @Nullable public EntityLiving getSource() { if (this.ax == null && this.ay != null && this.world instanceof WorldServer) { Entity entity = ((WorldServer) this.world).getEntity(this.ay); if (entity instanceof EntityLiving) { this.ax = (EntityLiving) entity; } } return this.ax; } @Override protected void a(NBTTagCompound nbttagcompound) { this.ticksLived = nbttagcompound.getInt("Age"); this.duration = nbttagcompound.getInt("Duration"); this.waitTime = nbttagcompound.getInt("WaitTime"); this.reapplicationDelay = nbttagcompound.getInt("ReapplicationDelay"); this.durationOnUse = nbttagcompound.getInt("DurationOnUse"); this.radiusOnUse = nbttagcompound.getFloat("RadiusOnUse"); this.radiusPerTick = nbttagcompound.getFloat("RadiusPerTick"); this.setRadius(nbttagcompound.getFloat("Radius")); this.ay = nbttagcompound.a("OwnerUUID"); if (nbttagcompound.hasKeyOfType("Particle", 8)) { try { this.setParticle(ArgumentParticle.b(new StringReader(nbttagcompound.getString("Particle")))); } catch (CommandSyntaxException commandsyntaxexception) { EntityAreaEffectCloud.LOGGER.warn("Couldn't load custom particle {}", nbttagcompound.getString("Particle"), commandsyntaxexception); } } if (nbttagcompound.hasKeyOfType("Color", 99)) { this.setColor(nbttagcompound.getInt("Color")); } if (nbttagcompound.hasKeyOfType("Potion", 8)) { this.a(PotionUtil.c(nbttagcompound)); } if (nbttagcompound.hasKeyOfType("Effects", 9)) { NBTTagList nbttaglist = nbttagcompound.getList("Effects", 10); this.effects.clear(); for (int i = 0; i < nbttaglist.size(); ++i) { MobEffect mobeffect = MobEffect.b(nbttaglist.getCompound(i)); if (mobeffect != null) { this.addEffect(mobeffect); } } } } @Override protected void b(NBTTagCompound nbttagcompound) { nbttagcompound.setInt("Age", this.ticksLived); nbttagcompound.setInt("Duration", this.duration); nbttagcompound.setInt("WaitTime", this.waitTime); nbttagcompound.setInt("ReapplicationDelay", this.reapplicationDelay); nbttagcompound.setInt("DurationOnUse", this.durationOnUse); nbttagcompound.setFloat("RadiusOnUse", this.radiusOnUse); nbttagcompound.setFloat("RadiusPerTick", this.radiusPerTick); nbttagcompound.setFloat("Radius", this.getRadius()); nbttagcompound.setString("Particle", this.getParticle().a()); if (this.ay != null) { nbttagcompound.a("OwnerUUID", this.ay); } if (this.hasColor) { nbttagcompound.setInt("Color", this.getColor()); } if (this.potionRegistry != Potions.EMPTY && this.potionRegistry != null) { nbttagcompound.setString("Potion", IRegistry.POTION.getKey(this.potionRegistry).toString()); } if (!this.effects.isEmpty()) { NBTTagList nbttaglist = new NBTTagList(); Iterator iterator = this.effects.iterator(); while (iterator.hasNext()) { MobEffect mobeffect = (MobEffect) iterator.next(); nbttaglist.add(mobeffect.a(new NBTTagCompound())); } nbttagcompound.set("Effects", nbttaglist); } } @Override public void a(DataWatcherObject<?> datawatcherobject) { if (EntityAreaEffectCloud.c.equals(datawatcherobject)) { this.updateSize(); } super.a(datawatcherobject); } @Override public EnumPistonReaction getPushReaction() { return EnumPistonReaction.IGNORE; } @Override public Packet<?> L() { return new PacketPlayOutSpawnEntity(this); } @Override public EntitySize a(EntityPose entitypose) { return EntitySize.b(this.getRadius() * 2.0F, 0.5F); } }