3
0
Mirror von https://github.com/PaperMC/Paper.git synchronisiert 2024-11-15 12:30:06 +01:00

SPIGOT-1638 / SPIGOT-1673: Rework Potions API

Dieser Commit ist enthalten in:
t00thpick1 2016-03-02 20:43:58 -05:00 committet von md_5
Ursprung 75286088fe
Commit 4a8818c5fd
20 geänderte Dateien mit 622 neuen und 121 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,25 @@
--- a/net/minecraft/server/EntityAreaEffectCloud.java
+++ b/net/minecraft/server/EntityAreaEffectCloud.java
@@ -91,6 +91,22 @@
}
+ // CraftBukkit start accessor methods
+ public void refreshEffects() {
+ if (!this.au) {
+ this.getDataWatcher().set(EntityAreaEffectCloud.b, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.e, (Collection) this.effects)))); // PAIL: rename
+ }
+ }
+
+ public String getType() {
+ return ((MinecraftKey) PotionRegistry.a.b(this.e)).toString(); // PAIL: rename
+ }
+
+ public void setType(String string) {
+ a(PotionRegistry.a.get(new MinecraftKey(string))); // PAIL: rename
+ }
+ // CraftBukkit end
+
public int getColor() {
return ((Integer) this.getDataWatcher().get(EntityAreaEffectCloud.b)).intValue();
}

Datei anzeigen

@ -101,7 +101,7 @@
}
}
}
@@ -138,10 +173,10 @@
@@ -138,19 +173,20 @@
}
}
}
@ -115,7 +115,10 @@
}
}
@@ -151,6 +186,7 @@
- private boolean n() {
+ public boolean n() { // PAIL: rename, access
return this.getItem().getItem() == Items.LINGERING_POTION;
}
private void a(BlockPosition blockposition) {
if (this.world.getType(blockposition).getBlock() == Blocks.FIRE) {

Datei anzeigen

@ -0,0 +1,37 @@
--- a/net/minecraft/server/EntityTippedArrow.java
+++ b/net/minecraft/server/EntityTippedArrow.java
@@ -10,7 +10,7 @@
private static final DataWatcherObject<Integer> f = DataWatcher.a(EntityTippedArrow.class, DataWatcherRegistry.b);
private PotionRegistry g;
- private final Set<MobEffect> h;
+ public final Set<MobEffect> h; // CraftBukkit private -> public
public EntityTippedArrow(World world) {
super(world);
@@ -98,6 +98,25 @@
}
}
+ // CraftBukkit start accessor methods
+ public void refreshEffects() {
+ this.getDataWatcher().set(EntityTippedArrow.f, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.g, (Collection) this.h)))); // PAIL: rename
+ }
+
+ public String getType() {
+ return ((MinecraftKey) PotionRegistry.a.b(this.g)).toString();
+ }
+
+ public void setType(String string) {
+ this.g = PotionRegistry.a.get(new MinecraftKey(string));
+ this.datawatcher.set(EntityTippedArrow.f, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.g, (Collection) this.h)))); // PAIL: rename
+ }
+
+ public boolean isTipped() {
+ return !(this.h.isEmpty() && this.g == Potions.a); // PAIL: rename
+ }
+ // CraftBukkit end
+
public int n() {
return ((Integer) this.datawatcher.get(EntityTippedArrow.f)).intValue();
}

Datei anzeigen

@ -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)) {

Datei anzeigen

@ -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 {
@ -106,26 +115,6 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
getHandle().setParticle(CraftParticle.toNMS(particle));
}
@Override
public List<PotionEffect> getEffects() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void addEffect(PotionEffect effect) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void removeEffect(PotionEffect effect) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void setEffects(List<PotionEffect> effects) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Color getColor() {
return Color.fromRGB(getHandle().getColor());
@ -135,4 +124,82 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
public void setColor(Color color) {
getHandle().setColor(color.asRGB());
}
@Override
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 clearCustomEffects() {
getHandle().effects.clear();
getHandle().refreshEffects();
}
@Override
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 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());
}
}

Datei anzeigen

@ -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); }
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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());

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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());
}
}

Datei anzeigen

@ -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,

Datei anzeigen

@ -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));

Datei anzeigen

@ -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;
List<MobEffect> mcEffects = PotionRegistry.a(CraftPotionUtil.fromBukkit(new PotionData(damage, upgraded, extended))).a();
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);
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);
}
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -30,6 +30,8 @@ import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionType;
import org.bukkit.support.AbstractTestingBase;
import org.junit.Test;
@ -177,6 +179,7 @@ public class ItemMetaTest extends AbstractTestingBase {
new StackProvider(Material.POTION) {
@Override ItemStack operate(final ItemStack cleanStack) {
final PotionMeta meta = (PotionMeta) cleanStack.getItemMeta();
meta.setBasePotionData(new PotionData(PotionType.UNCRAFTABLE, false, false));
meta.addCustomEffect(PotionEffectType.CONFUSION.createEffect(1, 1), false);
cleanStack.setItemMeta(meta);
return cleanStack;

Datei anzeigen

@ -14,19 +14,6 @@ import org.bukkit.support.AbstractTestingBase;
import org.junit.Test;
public class PotionTest extends AbstractTestingBase {
@Test
public void getEffects() {
for (PotionType type : PotionType.values()) {
for (PotionEffect effect : new Potion(type).getEffects()) {
PotionEffectType potionType = effect.getType();
assertThat(effect.getType(), is(sameInstance(PotionEffectType.getById(potionType.getId()))));
assertNotNull(potionType.getName(), PotionType.getByEffect(potionType));
}
}
}
@Test
public void testEffectCompleteness() throws Throwable {
Map<PotionType, String> effects = new EnumMap(PotionType.class);
@ -43,6 +30,6 @@ public class PotionTest extends AbstractTestingBase {
effects.put(enumType, enumType.name());
}
assertEquals(effects.entrySet().size(), PotionType.values().length - /* WATER */ 1);
assertEquals(effects.entrySet().size(), PotionType.values().length - /* PotionTypes with no Effects */ 5);
}
}

Datei anzeigen

@ -77,7 +77,6 @@ public abstract class AbstractTestingBase {
public static void setup() {
DispenserRegistry.c();
DummyServer.setup();
DummyPotions.setup();
DummyEnchantments.setup();
}
}

Datei anzeigen

@ -1,17 +0,0 @@
package org.bukkit.support;
import net.minecraft.server.MobEffects;
import org.bukkit.craftbukkit.potion.CraftPotionBrewer;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffectType;
public class DummyPotions {
static {
Potion.setPotionBrewer(new CraftPotionBrewer());
MobEffects.BLINDNESS.getClass();
PotionEffectType.stopAcceptingRegistrations();
}
public static void setup() {}
}