summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/bukkit/craftbukkit/CraftWorld.java47
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java91
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java9
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftLingeringPotion.java41
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java22
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftSplashPotion.java42
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java36
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java122
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java1
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java44
-rw-r--r--src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java44
-rw-r--r--src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java101
-rw-r--r--src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java24
13 files changed, 544 insertions, 80 deletions
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 9e0b5afa..2c82ecbb 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -36,6 +36,7 @@ import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.entity.*;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.LongHash;
import org.bukkit.entity.*;
@@ -53,6 +54,8 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.messaging.StandardMessenger;
+import org.bukkit.potion.PotionData;
+import org.bukkit.potion.PotionType;
import org.bukkit.util.Vector;
public class CraftWorld implements World {
@@ -360,14 +363,28 @@ public class CraftWorld implements World {
}
public Arrow spawnArrow(Location loc, Vector velocity, float speed, float spread) {
+ return spawnArrow(loc, velocity, speed, spread, Arrow.class);
+ }
+
+ public <T extends Arrow> T spawnArrow(Location loc, Vector velocity, float speed, float spread, Class<T> clazz) {
Validate.notNull(loc, "Can not spawn arrow with a null location");
Validate.notNull(velocity, "Can not spawn arrow with a null velocity");
+ Validate.notNull(clazz, "Can not spawn an arrow with no class");
+
+ EntityArrow arrow;
+ if (TippedArrow.class.isAssignableFrom(clazz)) {
+ arrow = new EntityTippedArrow(world);
+ ((EntityTippedArrow) arrow).setType(CraftPotionUtil.fromBukkit(new PotionData(PotionType.WATER, false, false)));
+ } else if (SpectralArrow.class.isAssignableFrom(clazz)) {
+ arrow = new EntitySpectralArrow(world);
+ } else {
+ arrow = new EntityTippedArrow(world);
+ }
- EntityArrow arrow = new EntityTippedArrow(world);
arrow.setPositionRotation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
arrow.shoot(velocity.getX(), velocity.getY(), velocity.getZ(), speed, spread);
world.addEntity(arrow);
- return (Arrow) arrow.getBukkitEntity();
+ return (T) arrow.getBukkitEntity();
}
public Entity spawnEntity(Location loc, EntityType entityType) {
@@ -922,7 +939,14 @@ public class CraftWorld implements World {
} else if (Egg.class.isAssignableFrom(clazz)) {
entity = new EntityEgg(world, x, y, z);
} else if (Arrow.class.isAssignableFrom(clazz)) {
- entity = new EntityTippedArrow(world);
+ if (TippedArrow.class.isAssignableFrom(clazz)) {
+ entity = new EntityTippedArrow(world);
+ ((EntityTippedArrow) entity).setType(CraftPotionUtil.fromBukkit(new PotionData(PotionType.WATER, false, false)));
+ } else if (SpectralArrow.class.isAssignableFrom(clazz)) {
+ entity = new EntitySpectralArrow(world);
+ } else {
+ entity = new EntityTippedArrow(world);
+ }
entity.setPositionRotation(x, y, z, 0, 0);
} else if (ThrownExpBottle.class.isAssignableFrom(clazz)) {
entity = new EntityThrownExpBottle(world);
@@ -931,15 +955,19 @@ public class CraftWorld implements World {
entity = new EntityEnderPearl(world, null);
entity.setPositionRotation(x, y, z, 0, 0);
} else if (ThrownPotion.class.isAssignableFrom(clazz)) {
- entity = new EntityPotion(world, x, y, z, CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.POTION, 1)));
+ if (LingeringPotion.class.isAssignableFrom(clazz)) {
+ entity = new EntityPotion(world, x, y, z, CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.LINGERING_POTION, 1)));
+ } else {
+ entity = new EntityPotion(world, x, y, z, CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.SPLASH_POTION, 1)));
+ }
} else if (Fireball.class.isAssignableFrom(clazz)) {
if (SmallFireball.class.isAssignableFrom(clazz)) {
entity = new EntitySmallFireball(world);
} else if (WitherSkull.class.isAssignableFrom(clazz)) {
entity = new EntityWitherSkull(world);
- } else if (DragonFireball.class.isAssignableFrom(clazz)){
+ } else if (DragonFireball.class.isAssignableFrom(clazz)) {
entity = new EntityDragonFireball(world);
- }else{
+ } else {
entity = new EntityLargeFireball(world);
}
entity.setPositionRotation(x, y, z, yaw, pitch);
@@ -1049,7 +1077,7 @@ public class CraftWorld implements World {
entity = new EntityRabbit(world);
} else if (Endermite.class.isAssignableFrom(clazz)) {
entity = new EntityEndermite(world);
- } else if (Guardian.class.isAssignableFrom(clazz)){
+ } else if (Guardian.class.isAssignableFrom(clazz)) {
entity = new EntityGuardian(world);
} else if (ArmorStand.class.isAssignableFrom(clazz)) {
entity = new EntityArmorStand(world, x, y, z);
@@ -1073,13 +1101,13 @@ public class CraftWorld implements World {
height = 9;
}
- BlockFace[] faces = new BlockFace[]{BlockFace.EAST,BlockFace.NORTH,BlockFace.WEST,BlockFace.SOUTH};
+ BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH};
final BlockPosition pos = new BlockPosition((int) x, (int) y, (int) z);
for (BlockFace dir : faces) {
net.minecraft.server.Block nmsBlock = CraftMagicNumbers.getBlock(block.getRelative(dir));
if (nmsBlock.getBlockData().getMaterial().isBuildable() || BlockDiodeAbstract.isDiode(nmsBlock.getBlockData())) {
boolean taken = false;
- AxisAlignedBB bb = EntityHanging.calculateBoundingBox(null, pos,CraftBlock.blockFaceToNotch(dir).opposite(),width,height);
+ AxisAlignedBB bb = EntityHanging.calculateBoundingBox(null, pos, CraftBlock.blockFaceToNotch(dir).opposite(), width, height);
List<net.minecraft.server.Entity> list = (List<net.minecraft.server.Entity>) world.getEntities(null, bb);
for (Iterator<net.minecraft.server.Entity> it = list.iterator(); !taken && it.hasNext();) {
net.minecraft.server.Entity e = it.next();
@@ -1096,7 +1124,6 @@ public class CraftWorld implements World {
}
EnumDirection dir = CraftBlock.blockFaceToNotch(face).opposite();
-
if (Painting.class.isAssignableFrom(clazz)) {
entity = new EntityPainting(world, new BlockPosition((int) x, (int) y, (int) z), dir);
} else if (ItemFrame.class.isAssignableFrom(clazz)) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
index f32b9e2f..e8b8787b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
@@ -2,13 +2,22 @@ package org.bukkit.craftbukkit.entity;
import java.util.List;
import net.minecraft.server.EntityAreaEffectCloud;
+import net.minecraft.server.MobEffect;
+import net.minecraft.server.MobEffectList;
+
+import org.apache.commons.lang.Validate;
import org.bukkit.Color;
import org.bukkit.Particle;
import org.bukkit.craftbukkit.CraftParticle;
import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.EntityType;
import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionData;
+
+import com.google.common.collect.ImmutableList;
public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud {
@@ -107,32 +116,90 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
}
@Override
- public List<PotionEffect> getEffects() {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ public Color getColor() {
+ return Color.fromRGB(getHandle().getColor());
}
@Override
- public void addEffect(PotionEffect effect) {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ public void setColor(Color color) {
+ getHandle().setColor(color.asRGB());
}
@Override
- public void removeEffect(PotionEffect effect) {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ public boolean addCustomEffect(PotionEffect effect, boolean override) {
+ int effectId = effect.getType().getId();
+ MobEffect existing = null;
+ for (MobEffect mobEffect : getHandle().effects) {
+ if (MobEffectList.getId(mobEffect.getMobEffect()) == effectId) {
+ existing = mobEffect;
+ }
+ }
+ if (existing != null) {
+ if (!override) {
+ return false;
+ }
+ getHandle().effects.remove(existing);
+ }
+ getHandle().a(CraftPotionUtil.fromBukkit(effect));
+ getHandle().refreshEffects();
+ return true;
}
@Override
- public void setEffects(List<PotionEffect> effects) {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ public void clearCustomEffects() {
+ getHandle().effects.clear();
+ getHandle().refreshEffects();
}
@Override
- public Color getColor() {
- return Color.fromRGB(getHandle().getColor());
+ public List<PotionEffect> getCustomEffects() {
+ ImmutableList.Builder<PotionEffect> builder = ImmutableList.builder();
+ for (MobEffect effect : getHandle().effects) {
+ builder.add(CraftPotionUtil.toBukkit(effect));
+ }
+ return builder.build();
}
@Override
- public void setColor(Color color) {
- getHandle().setColor(color.asRGB());
+ public boolean hasCustomEffect(PotionEffectType type) {
+ for (MobEffect effect : getHandle().effects) {
+ if (CraftPotionUtil.equals(effect.getMobEffect(), type)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean hasCustomEffects() {
+ return !getHandle().effects.isEmpty();
+ }
+
+ @Override
+ public boolean removeCustomEffect(PotionEffectType effect) {
+ int effectId = effect.getId();
+ MobEffect existing = null;
+ for (MobEffect mobEffect : getHandle().effects) {
+ if (MobEffectList.getId(mobEffect.getMobEffect()) == effectId) {
+ existing = mobEffect;
+ }
+ }
+ if (existing == null) {
+ return false;
+ }
+ getHandle().effects.remove(existing);
+ getHandle().refreshEffects();
+ return true;
+ }
+
+ @Override
+ public void setBasePotionData(PotionData data) {
+ Validate.notNull(data, "PotionData cannot be null");
+ getHandle().setType(CraftPotionUtil.fromBukkit(data));
+ }
+
+ @Override
+ public PotionData getBasePotionData() {
+ return CraftPotionUtil.toBukkit(getHandle().getType());
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 22d08a20..7f10a0f7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -138,12 +138,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
else { return new CraftComplexPart(server, (EntityComplexPart) entity); }
}
else if (entity instanceof EntityExperienceOrb) { return new CraftExperienceOrb(server, (EntityExperienceOrb) entity); }
+ else if (entity instanceof EntityTippedArrow) {
+ if (((EntityTippedArrow) entity).isTipped()) { return new CraftTippedArrow(server, (EntityTippedArrow) entity); }
+ else { return new CraftArrow(server, (EntityArrow) entity); }
+ }
else if (entity instanceof EntityArrow) { return new CraftArrow(server, (EntityArrow) entity); }
else if (entity instanceof EntityBoat) { return new CraftBoat(server, (EntityBoat) entity); }
else if (entity instanceof EntityProjectile) {
if (entity instanceof EntityEgg) { return new CraftEgg(server, (EntityEgg) entity); }
else if (entity instanceof EntitySnowball) { return new CraftSnowball(server, (EntitySnowball) entity); }
- else if (entity instanceof EntityPotion) { return new CraftThrownPotion(server, (EntityPotion) entity); }
+ else if (entity instanceof EntityPotion) {
+ if (!((EntityPotion) entity).n()) { return new CraftSplashPotion(server, (EntityPotion) entity); }
+ else { return new CraftLingeringPotion(server, (EntityPotion) entity); }
+ }
else if (entity instanceof EntityEnderPearl) { return new CraftEnderPearl(server, (EntityEnderPearl) entity); }
else if (entity instanceof EntityThrownExpBottle) { return new CraftThrownExpBottle(server, (EntityThrownExpBottle) entity); }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLingeringPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLingeringPotion.java
new file mode 100644
index 00000000..52cd654a
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLingeringPotion.java
@@ -0,0 +1,41 @@
+package org.bukkit.craftbukkit.entity;
+
+import net.minecraft.server.EntityPotion;
+import org.apache.commons.lang.Validate;
+import org.bukkit.Material;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.entity.EntityType;
+import org.bukkit.inventory.ItemStack;
+
+public class CraftLingeringPotion extends CraftThrownPotion {
+
+ public CraftLingeringPotion(CraftServer server, EntityPotion entity) {
+ super(server, entity);
+ }
+
+ public void setItem(ItemStack item) {
+ // The ItemStack must not be null.
+ Validate.notNull(item, "ItemStack cannot be null.");
+
+ // The ItemStack must be a potion.
+ Validate.isTrue(item.getType() == Material.LINGERING_POTION, "ItemStack must be a lingering potion. This item stack was " + item.getType() + ".");
+
+ getHandle().setItem(CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public EntityPotion getHandle() {
+ return (EntityPotion) entity;
+ }
+
+ @Override
+ public String toString() {
+ return "CraftLingeringPotion";
+ }
+
+ @Override
+ public EntityType getType() {
+ return EntityType.LINGERING_POTION;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index e8aff909..c17b6144 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -26,6 +26,7 @@ import net.minecraft.server.EntitySmallFireball;
import net.minecraft.server.EntitySnowball;
import net.minecraft.server.EntityThrownExpBottle;
import net.minecraft.server.EntityTippedArrow;
+import net.minecraft.server.EntitySpectralArrow;
import net.minecraft.server.EntityWither;
import net.minecraft.server.EntityWitherSkull;
import net.minecraft.server.GenericAttributes;
@@ -42,6 +43,7 @@ import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftEntityEquipment;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.DragonFireball;
import org.bukkit.entity.Egg;
@@ -51,19 +53,24 @@ import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.Fish;
import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.LingeringPotion;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.SmallFireball;
import org.bukkit.entity.Snowball;
+import org.bukkit.entity.SpectralArrow;
import org.bukkit.entity.ThrownExpBottle;
import org.bukkit.entity.ThrownPotion;
+import org.bukkit.entity.TippedArrow;
import org.bukkit.entity.WitherSkull;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionType;
import org.bukkit.util.BlockIterator;
import org.bukkit.util.NumberConversions;
import org.bukkit.util.Vector;
@@ -337,10 +344,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
launch = new EntityEnderPearl(world, getHandle());
((EntityProjectile) launch).a(getHandle(), getHandle().pitch, getHandle().yaw, 0.0F, 1.5F, 1.0F); // ItemEnderPearl
} else if (Arrow.class.isAssignableFrom(projectile)) {
- launch = new EntityTippedArrow(world, getHandle());
+ if (TippedArrow.class.isAssignableFrom(projectile)) {
+ launch = new EntityTippedArrow(world);
+ ((EntityTippedArrow) launch).setType(CraftPotionUtil.fromBukkit(new PotionData(PotionType.WATER, false, false)));
+ } else if (SpectralArrow.class.isAssignableFrom(projectile)) {
+ launch = new EntitySpectralArrow(world);
+ } else {
+ launch = new EntityTippedArrow(world);
+ }
((EntityArrow) launch).a(getHandle(), getHandle().pitch, getHandle().yaw, 0.0F, 3.0F, 1.0F); // ItemBow
} else if (ThrownPotion.class.isAssignableFrom(projectile)) {
- launch = new EntityPotion(world, getHandle(), CraftItemStack.asNMSCopy(new ItemStack(Material.POTION, 1)));
+ if (LingeringPotion.class.isAssignableFrom(projectile)) {
+ launch = new EntityPotion(world, getHandle(), CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.LINGERING_POTION, 1)));
+ } else {
+ launch = new EntityPotion(world, getHandle(), CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.SPLASH_POTION, 1)));
+ }
((EntityProjectile) launch).a(getHandle(), getHandle().pitch, getHandle().yaw, -20.0F, 0.5F, 1.0F); // ItemSplashPotion
} else if (ThrownExpBottle.class.isAssignableFrom(projectile)) {
launch = new EntityThrownExpBottle(world, getHandle());
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSplashPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSplashPotion.java
new file mode 100644
index 00000000..863a6c27
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSplashPotion.java
@@ -0,0 +1,42 @@
+package org.bukkit.craftbukkit.entity;
+
+import net.minecraft.server.EntityPotion;
+import org.apache.commons.lang.Validate;
+import org.bukkit.Material;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.entity.EntityType;
+import org.bukkit.inventory.ItemStack;
+
+public class CraftSplashPotion extends CraftThrownPotion {
+
+ public CraftSplashPotion(CraftServer server, EntityPotion entity) {
+ super(server, entity);
+ }
+
+ @Override
+ public void setItem(ItemStack item) {
+ // The ItemStack must not be null.
+ Validate.notNull(item, "ItemStack cannot be null.");
+
+ // The ItemStack must be a potion.
+ Validate.isTrue(item.getType() == Material.SPLASH_POTION, "ItemStack must be a splash potion. This item stack was " + item.getType() + ".");
+
+ getHandle().setItem(CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public EntityPotion getHandle() {
+ return (EntityPotion) entity;
+ }
+
+ @Override
+ public String toString() {
+ return "CraftSplashPotion";
+ }
+
+ @Override
+ public EntityType getType() {
+ return EntityType.SPLASH_POTION;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
index 092e9fba..b1953993 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
@@ -1,55 +1,41 @@
package org.bukkit.craftbukkit.entity;
import java.util.Collection;
-
import net.minecraft.server.EntityPotion;
+import net.minecraft.server.MobEffect;
+import net.minecraft.server.PotionUtil;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
-public class CraftThrownPotion extends CraftProjectile implements ThrownPotion {
+import com.google.common.collect.ImmutableList;
+
+public abstract class CraftThrownPotion extends CraftProjectile implements ThrownPotion {
public CraftThrownPotion(CraftServer server, EntityPotion entity) {
super(server, entity);
}
- // TODO: This one does not handle custom NBT potion effects does it?
- // In that case this method could be said to be misleading or incorrect
public Collection<PotionEffect> getEffects() {
- return Potion.getBrewer().getEffectsFromDamage(getHandle().getItem().getData());
+ ImmutableList.Builder<PotionEffect> builder = ImmutableList.builder();
+ for (MobEffect effect : PotionUtil.getEffects(getHandle().getItem())) {
+ builder.add(CraftPotionUtil.toBukkit(effect));
+ }
+ return builder.build();
}
public ItemStack getItem() {
return CraftItemStack.asBukkitCopy(getHandle().getItem());
}
- public void setItem(ItemStack item) {
- // The ItemStack must not be null.
- Validate.notNull(item, "ItemStack cannot be null.");
-
- // The ItemStack must be a potion.
- Validate.isTrue(item.getType() == Material.POTION, "ItemStack must be a potion. This item stack was " + item.getType() + ".");
-
- getHandle().setItem(CraftItemStack.asNMSCopy(item));
- }
-
@Override
public EntityPotion getHandle() {
return (EntityPotion) entity;
}
-
- @Override
- public String toString() {
- return "CraftThrownPotion";
- }
-
- public EntityType getType() {
- return EntityType.SPLASH_POTION;
- }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
new file mode 100644
index 00000000..79abae9c
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
@@ -0,0 +1,122 @@
+package org.bukkit.craftbukkit.entity;
+
+import java.util.List;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.TippedArrow;
+import org.bukkit.potion.PotionData;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionType;
+
+import com.google.common.collect.ImmutableList;
+
+import net.minecraft.server.EntityTippedArrow;
+import net.minecraft.server.MobEffect;
+import net.minecraft.server.MobEffectList;
+
+public class CraftTippedArrow extends CraftArrow implements TippedArrow {
+
+ public CraftTippedArrow(CraftServer server, EntityTippedArrow entity) {
+ super(server, entity);
+ }
+
+ @Override
+ public EntityTippedArrow getHandle() {
+ return (EntityTippedArrow) entity;
+ }
+
+ @Override
+ public String toString() {
+ return "CraftTippedArrow";
+ }
+
+ @Override
+ public EntityType getType() {
+ return EntityType.TIPPED_ARROW;
+ }
+
+ @Override
+ public boolean addCustomEffect(PotionEffect effect, boolean override) {
+ int effectId = effect.getType().getId();
+ MobEffect existing = null;
+ for (MobEffect mobEffect : getHandle().h) {
+ if (MobEffectList.getId(mobEffect.getMobEffect()) == effectId) {
+ existing = mobEffect;
+ }
+ }
+ if (existing != null) {
+ if (!override) {
+ return false;
+ }
+ getHandle().h.remove(existing);
+ }
+ getHandle().a(CraftPotionUtil.fromBukkit(effect));
+ getHandle().refreshEffects();
+ return true;
+ }
+
+ @Override
+ public void clearCustomEffects() {
+ Validate.isTrue(getBasePotionData().getType() != PotionType.UNCRAFTABLE, "Tipped Arrows must have at least 1 effect");
+ getHandle().h.clear();
+ getHandle().refreshEffects();
+ }
+
+ @Override
+ public List<PotionEffect> getCustomEffects() {
+ ImmutableList.Builder<PotionEffect> builder = ImmutableList.builder();
+ for (MobEffect effect : getHandle().h) {
+ builder.add(CraftPotionUtil.toBukkit(effect));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public boolean hasCustomEffect(PotionEffectType type) {
+ for (MobEffect effect : getHandle().h) {
+ if (CraftPotionUtil.equals(effect.getMobEffect(), type)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean hasCustomEffects() {
+ return !getHandle().h.isEmpty();
+ }
+
+ @Override
+ public boolean removeCustomEffect(PotionEffectType effect) {
+ int effectId = effect.getId();
+ MobEffect existing = null;
+ for (MobEffect mobEffect : getHandle().h) {
+ if (MobEffectList.getId(mobEffect.getMobEffect()) == effectId) {
+ existing = mobEffect;
+ }
+ }
+ if (existing == null) {
+ return false;
+ }
+ Validate.isTrue(getBasePotionData().getType() != PotionType.UNCRAFTABLE || getHandle().h.size() != 1, "Tipped Arrows must have at least 1 effect");
+ getHandle().h.remove(existing);
+ getHandle().refreshEffects();
+ return true;
+ }
+
+ @Override
+ public void setBasePotionData(PotionData data) {
+ Validate.notNull(data, "PotionData cannot be null");
+ Validate.isTrue(data.getType() != PotionType.UNCRAFTABLE || !getHandle().h.isEmpty(), "Tipped Arrows must have at least 1 effect");
+ getHandle().setType(CraftPotionUtil.fromBukkit(data));
+ }
+
+ @Override
+ public PotionData getBasePotionData() {
+ return CraftPotionUtil.toBukkit(getHandle().getType());
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 7c3adbbf..294f6c90 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -802,6 +802,7 @@ class CraftMetaItem implements ItemMeta, Repairable {
HIDEFLAGS.NBT,
CraftMetaMap.MAP_SCALING.NBT,
CraftMetaPotion.POTION_EFFECTS.NBT,
+ CraftMetaPotion.DEFAULT_POTION.NBT,
CraftMetaSkull.SKULL_OWNER.NBT,
CraftMetaSkull.SKULL_PROFILE.NBT,
CraftMetaBlockState.BLOCK_ENTITY_TAG.NBT,
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
index f6845307..50612a91 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
@@ -12,9 +12,12 @@ import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.inventory.meta.PotionMeta;
+import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionType;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap.Builder;
@@ -27,7 +30,9 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
static final ItemMetaKey SHOW_PARTICLES = new ItemMetaKey("ShowParticles", "has-particles");
static final ItemMetaKey POTION_EFFECTS = new ItemMetaKey("CustomPotionEffects", "custom-effects");
static final ItemMetaKey ID = new ItemMetaKey("Id", "potion-id");
+ static final ItemMetaKey DEFAULT_POTION = new ItemMetaKey("Potion", "potion-type");
+ private String type;
private List<PotionEffect> customEffects;
CraftMetaPotion(CraftMetaItem meta) {
@@ -36,6 +41,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
return;
}
CraftMetaPotion potionMeta = (CraftMetaPotion) meta;
+ this.type = potionMeta.type;
if (potionMeta.hasCustomEffects()) {
this.customEffects = new ArrayList<PotionEffect>(potionMeta.customEffects);
}
@@ -43,7 +49,9 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
CraftMetaPotion(NBTTagCompound tag) {
super(tag);
-
+ if (tag.hasKey(DEFAULT_POTION.NBT)) {
+ type = tag.getString(DEFAULT_POTION.NBT);
+ }
if (tag.hasKey(POTION_EFFECTS.NBT)) {
NBTTagList list = tag.getList(POTION_EFFECTS.NBT, 10);
int length = list.size();
@@ -63,6 +71,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
CraftMetaPotion(Map<String, Object> map) {
super(map);
+ type = SerializableMeta.getString(map, DEFAULT_POTION.BUKKIT, true);
Iterable<?> rawEffectList = SerializableMeta.getObject(Iterable.class, map, POTION_EFFECTS.BUKKIT, true);
if (rawEffectList == null) {
@@ -80,6 +89,9 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
@Override
void applyToItem(NBTTagCompound tag) {
super.applyToItem(tag);
+ // NBT expects a PotionType under all circumstances, but ItemMeta API contract expects that a fresh stack have blank meta
+ // As such we will equate the NMS default type of "Empty"/UNCRAFTABLE to be null
+ tag.setString(DEFAULT_POTION.NBT, type != null ? type : CraftPotionUtil.fromBukkit(new PotionData(PotionType.UNCRAFTABLE, false, false)));
if (customEffects != null) {
NBTTagList effectList = new NBTTagList();
tag.set(POTION_EFFECTS.NBT, effectList);
@@ -102,7 +114,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
}
boolean isPotionEmpty() {
- return !(hasCustomEffects());
+ return (type == null) && !(hasCustomEffects());
}
@Override
@@ -121,12 +133,32 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
@Override
public CraftMetaPotion clone() {
CraftMetaPotion clone = (CraftMetaPotion) super.clone();
+ clone.type = type;
if (this.customEffects != null) {
clone.customEffects = new ArrayList<PotionEffect>(this.customEffects);
}
return clone;
}
+ @Override
+ public void setBasePotionData(PotionData data) {
+ Validate.notNull(data, "PotionData cannot be null");
+ PotionType type = data.getType();
+ if (type == PotionType.UNCRAFTABLE) {
+ this.type = null;
+ return;
+ }
+ this.type = CraftPotionUtil.fromBukkit(data);
+ }
+
+ @Override
+ public PotionData getBasePotionData() {
+ if (type == null) {
+ return new PotionData(PotionType.UNCRAFTABLE, false, false);
+ }
+ return CraftPotionUtil.toBukkit(type);
+ }
+
public boolean hasCustomEffects() {
return customEffects != null;
}
@@ -225,6 +257,9 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
int applyHash() {
final int original;
int hash = original = super.applyHash();
+ if (type != null) {
+ hash = 73 * hash + type.hashCode();
+ }
if (hasCustomEffects()) {
hash = 73 * hash + customEffects.hashCode();
}
@@ -239,7 +274,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
if (meta instanceof CraftMetaPotion) {
CraftMetaPotion that = (CraftMetaPotion) meta;
- return (this.hasCustomEffects() ? that.hasCustomEffects() && this.customEffects.equals(that.customEffects) : !that.hasCustomEffects());
+ return ((type == null && that.type == null) || type.equals(that.type)) && (this.hasCustomEffects() ? that.hasCustomEffects() && this.customEffects.equals(that.customEffects) : !that.hasCustomEffects());
}
return true;
}
@@ -252,6 +287,9 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
@Override
Builder<String, Object> serialize(Builder<String, Object> builder) {
super.serialize(builder);
+ if (type != null) {
+ builder.put(DEFAULT_POTION.BUKKIT, type);
+ }
if (hasCustomEffects()) {
builder.put(POTION_EFFECTS.BUKKIT, ImmutableList.copyOf(this.customEffects));
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
index 5305f9ad..897b7a7a 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
@@ -5,48 +5,44 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
-import net.minecraft.server.ItemStack;
-import net.minecraft.server.Items;
import net.minecraft.server.MobEffect;
-import net.minecraft.server.MobEffectList;
-import net.minecraft.server.PotionUtil;
+import net.minecraft.server.PotionRegistry;
-import org.bukkit.Color;
import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionType;
import org.bukkit.potion.PotionBrewer;
+import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
public class CraftPotionBrewer implements PotionBrewer {
- private static final Map<Integer, Collection<PotionEffect>> cache = Maps.newHashMap();
+ private static final Map<PotionType, Collection<PotionEffect>> cache = Maps.newHashMap();
- public Collection<PotionEffect> getEffectsFromDamage(int damage) {
+ public Collection<PotionEffect> getEffects(PotionType damage, boolean upgraded, boolean extended) {
if (cache.containsKey(damage))
return cache.get(damage);
- List<?> mcEffects = PotionUtil.getEffects(new ItemStack(Items.POTION, 1, damage));
- List<PotionEffect> effects = new ArrayList<PotionEffect>();
- if (mcEffects == null)
- return effects;
-
- for (Object raw : mcEffects) {
- if (raw == null || !(raw instanceof MobEffect))
- continue;
- MobEffect mcEffect = (MobEffect) raw;
- PotionEffect effect = new PotionEffect(PotionEffectType.getById(MobEffectList.getId(mcEffect.getMobEffect())),
- mcEffect.getDuration(), mcEffect.getAmplifier(), true, true, Color.fromRGB(mcEffect.getMobEffect().getColor()));
- // Minecraft PotionBrewer applies duration modifiers automatically.
- effects.add(effect);
+ List<MobEffect> mcEffects = PotionRegistry.a(CraftPotionUtil.fromBukkit(new PotionData(damage, upgraded, extended))).a();
+
+ ImmutableList.Builder<PotionEffect> builder = new ImmutableList.Builder<PotionEffect>();
+ for (MobEffect effect : mcEffects) {
+ builder.add(CraftPotionUtil.toBukkit(effect));
}
- cache.put(damage, effects);
+ cache.put(damage, builder.build());
- return effects;
+ return cache.get(damage);
+ }
+
+ @Override
+ public Collection<PotionEffect> getEffectsFromDamage(int damage) {
+ return new ArrayList<PotionEffect>();
}
+ @Override
public PotionEffect createEffect(PotionEffectType potion, int duration, int amplifier) {
- return new PotionEffect(potion, potion.isInstant() ? 1 : (int) (duration * potion.getDurationModifier()),
- amplifier);
+ return new PotionEffect(potion, potion.isInstant() ? 1 : (int) (duration * potion.getDurationModifier()), amplifier);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
new file mode 100644
index 00000000..6126c0a9
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
@@ -0,0 +1,101 @@
+package org.bukkit.craftbukkit.potion;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.ImmutableBiMap;
+
+import net.minecraft.server.MobEffect;
+import net.minecraft.server.MobEffectList;
+
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionType;
+import org.bukkit.potion.PotionData;
+
+public class CraftPotionUtil {
+
+ private static final BiMap<PotionType, String> regular = ImmutableBiMap.<PotionType, String>builder()
+ .put(PotionType.UNCRAFTABLE, "minecraft:empty")
+ .put(PotionType.WATER, "minecraft:water")
+ .put(PotionType.MUNDANE, "minecraft:mundane")
+ .put(PotionType.THICK, "minecraft:thick")
+ .put(PotionType.AWKWARD, "minecraft:awkward")
+ .put(PotionType.NIGHT_VISION, "minecraft:night_vision")
+ .put(PotionType.INVISIBILITY, "minecraft:invisibility")
+ .put(PotionType.JUMP, "minecraft:leaping")
+ .put(PotionType.FIRE_RESISTANCE, "minecraft:fire_resistance")
+ .put(PotionType.SPEED, "minecraft:swiftness")
+ .put(PotionType.SLOWNESS, "minecraft:slowness")
+ .put(PotionType.WATER_BREATHING, "minecraft:water_breathing")
+ .put(PotionType.INSTANT_HEAL, "minecraft:healing")
+ .put(PotionType.INSTANT_DAMAGE, "minecraft:harming")
+ .put(PotionType.POISON, "minecraft:poison")
+ .put(PotionType.REGEN, "minecraft:regeneration")
+ .put(PotionType.STRENGTH, "minecraft:strength")
+ .put(PotionType.WEAKNESS, "minecraft:weakness")
+ .put(PotionType.LUCK, "minecraft:luck")
+ .build();
+ private static final BiMap<PotionType, String> upgradeable = ImmutableBiMap.<PotionType, String>builder()
+ .put(PotionType.JUMP, "minecraft:strong_leaping")
+ .put(PotionType.SPEED, "minecraft:strong_swiftness")
+ .put(PotionType.INSTANT_HEAL, "minecraft:strong_healing")
+ .put(PotionType.INSTANT_DAMAGE, "minecraft:strong_harming")
+ .put(PotionType.POISON, "minecraft:strong_poison")
+ .put(PotionType.REGEN, "minecraft:strong_regeneration")
+ .put(PotionType.STRENGTH, "minecraft:strong_strength")
+ .build();
+ private static final BiMap<PotionType, String> extendable = ImmutableBiMap.<PotionType, String>builder()
+ .put(PotionType.NIGHT_VISION, "minecraft:long_night_vision")
+ .put(PotionType.INVISIBILITY, "minecraft:long_invisibility")
+ .put(PotionType.JUMP, "minecraft:long_leaping")
+ .put(PotionType.FIRE_RESISTANCE, "minecraft:long_fire_resistance")
+ .put(PotionType.SPEED, "minecraft:long_swiftness")
+ .put(PotionType.SLOWNESS, "minecraft:long_slowness")
+ .put(PotionType.WATER_BREATHING, "minecraft:long_water_breathing")
+ .put(PotionType.POISON, "minecraft:long_poison")
+ .put(PotionType.REGEN, "minecraft:long_regeneration")
+ .put(PotionType.STRENGTH, "minecraft:long_strength")
+ .put(PotionType.WEAKNESS, "minecraft:long_weakness")
+ .build();
+
+ public static String fromBukkit(PotionData data) {
+ if (data.isUpgraded()) {
+ return upgradeable.get(data.getType());
+ }
+ if (data.isExtended()) {
+ return extendable.get(data.getType());
+ }
+ return regular.get(data.getType());
+ }
+
+ public static PotionData toBukkit(String type) {
+ PotionType potionType = null;
+ potionType = extendable.inverse().get(type);
+ if (potionType != null) {
+ return new PotionData(potionType, true, false);
+ }
+ potionType = upgradeable.inverse().get(type);
+ if (potionType != null) {
+ return new PotionData(potionType, false, true);
+ }
+ return new PotionData(regular.inverse().get(type), false, false);
+ }
+
+ public static MobEffect fromBukkit(PotionEffect effect) {
+ MobEffectList type = MobEffectList.fromId(effect.getType().getId());
+ return new MobEffect(type, effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles());
+ }
+
+ public static PotionEffect toBukkit(MobEffect effect) {
+ PotionEffectType type = PotionEffectType.getById(MobEffectList.getId(effect.getMobEffect()));
+ int amp = effect.getAmplifier();
+ int duration = effect.getDuration();
+ boolean ambient = effect.isAmbient();
+ boolean particles = effect.isShowParticles();
+ return new PotionEffect(type, duration, amp, ambient, particles);
+ }
+
+ public static boolean equals(MobEffectList mobEffect, PotionEffectType type) {
+ PotionEffectType typeV = PotionEffectType.getById(MobEffectList.getId(mobEffect));
+ return typeV.equals(type);
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
index 6c3c1eae..057ae243 100644
--- a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
+++ b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
@@ -6,17 +6,23 @@ import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Egg;
import org.bukkit.entity.EnderPearl;
import org.bukkit.entity.Fireball;
+import org.bukkit.entity.LingeringPotion;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.SmallFireball;
import org.bukkit.entity.Snowball;
+import org.bukkit.entity.SpectralArrow;
import org.bukkit.entity.ThrownExpBottle;
import org.bukkit.entity.ThrownPotion;
+import org.bukkit.entity.TippedArrow;
import org.bukkit.entity.WitherSkull;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionData;
+import org.bukkit.potion.PotionType;
import org.bukkit.projectiles.BlockProjectileSource;
import org.bukkit.util.Vector;
@@ -30,6 +36,7 @@ import net.minecraft.server.EntityPotion;
import net.minecraft.server.EntityProjectile;
import net.minecraft.server.EntitySmallFireball;
import net.minecraft.server.EntitySnowball;
+import net.minecraft.server.EntitySpectralArrow;
import net.minecraft.server.EntityThrownExpBottle;
import net.minecraft.server.EntityTippedArrow;
import net.minecraft.server.EntityWitherSkull;
@@ -78,9 +85,20 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
} else if (ThrownExpBottle.class.isAssignableFrom(projectile)) {
launch = new EntityThrownExpBottle(world, iposition.getX(), iposition.getY(), iposition.getZ());
} else if (ThrownPotion.class.isAssignableFrom(projectile)) {
- launch = new EntityPotion(world, iposition.getX(), iposition.getY(), iposition.getZ(), CraftItemStack.asNMSCopy(new ItemStack(Material.POTION, 1)));
+ if (LingeringPotion.class.isAssignableFrom(projectile)) {
+ launch = new EntityPotion(world, iposition.getX(), iposition.getY(), iposition.getZ(), CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.LINGERING_POTION, 1)));
+ } else {
+ launch = new EntityPotion(world, iposition.getX(), iposition.getY(), iposition.getZ(), CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.SPLASH_POTION, 1)));
+ }
} else if (Arrow.class.isAssignableFrom(projectile)) {
- launch = new EntityTippedArrow(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ if (TippedArrow.class.isAssignableFrom(projectile)) {
+ launch = new EntityTippedArrow(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ ((EntityTippedArrow) launch).setType(CraftPotionUtil.fromBukkit(new PotionData(PotionType.WATER, false, false)));
+ } else if (SpectralArrow.class.isAssignableFrom(projectile)) {
+ launch = new EntitySpectralArrow(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ } else {
+ launch = new EntityTippedArrow(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ }
((EntityArrow) launch).fromPlayer = EntityArrow.PickupStatus.ALLOWED;
((EntityArrow) launch).projectileSource = this;
} else if (Fireball.class.isAssignableFrom(projectile)) {
@@ -111,7 +129,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
((EntityFireball) launch).dirY = d4 / d6 * 0.1D;
((EntityFireball) launch).dirZ = d5 / d6 * 0.1D;
}
-
+
((EntityFireball) launch).projectileSource = this;
}