diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java index d19bc0af7e..360605f4dd 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -63,7 +63,7 @@ public abstract class EntityLiving extends Entity { protected EntityLiving lastDamager = null; public int aJ = 0; public int aK = 0; - protected HashMap effects = new HashMap(); + public HashMap effects = new HashMap(); // CraftBukkit - protected -> public private boolean b = true; private int c; private ControllerLook lookController; diff --git a/src/main/java/net/minecraft/server/MobEffectList.java b/src/main/java/net/minecraft/server/MobEffectList.java index 4d178290c5..ae27a5ac37 100644 --- a/src/main/java/net/minecraft/server/MobEffectList.java +++ b/src/main/java/net/minecraft/server/MobEffectList.java @@ -2,7 +2,9 @@ package net.minecraft.server; // CraftBukkit start import org.bukkit.Bukkit; +import org.bukkit.potion.PotionEffectType; import org.bukkit.craftbukkit.event.CraftEventFactory; +import org.bukkit.craftbukkit.potion.CraftPotionEffectType; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; @@ -62,6 +64,8 @@ public class MobEffectList { } this.N = j; + + PotionEffectType.registerPotionEffectType(new CraftPotionEffectType(this)); // CraftBukkit } protected MobEffectList a(int i, int j) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index caeb3844e3..ac018e97de 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -42,6 +42,7 @@ import net.minecraft.server.EntityPlayer; import net.minecraft.server.EntityTracker; import net.minecraft.server.IProgressUpdate; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.MobEffectList; import net.minecraft.server.PropertyManager; import net.minecraft.server.ServerConfigurationManager; import net.minecraft.server.ServerNBTManager; @@ -74,6 +75,7 @@ import org.bukkit.craftbukkit.inventory.CraftRecipe; import org.bukkit.craftbukkit.inventory.CraftShapedRecipe; import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; import org.bukkit.craftbukkit.map.CraftMapView; +import org.bukkit.craftbukkit.potion.CraftPotionBrewer; import org.bukkit.scheduler.BukkitWorker; import org.bukkit.craftbukkit.scheduler.CraftScheduler; import org.bukkit.craftbukkit.util.DatFileFilter; @@ -82,6 +84,8 @@ import org.bukkit.util.permissions.DefaultPermissions; import org.bukkit.event.world.WorldInitEvent; import org.bukkit.permissions.Permission; import org.bukkit.plugin.PluginLoadOrder; +import org.bukkit.potion.Potion; +import org.bukkit.potion.PotionEffectType; import org.bukkit.plugin.messaging.StandardMessenger; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.SafeConstructor; @@ -114,9 +118,13 @@ public final class CraftServer implements Server { Bukkit.setServer(this); - // Register all the Enchantments now so we can stop new registration immediately after + // Register all the Enchantments and PotionTypes now so we can stop new registration immediately after Enchantment.DAMAGE_ALL.getClass(); org.bukkit.enchantments.Enchantment.stopAcceptingRegistrations(); + + Potion.setPotionBrewer(new CraftPotionBrewer()); + MobEffectList.BLINDNESS.getClass(); + PotionEffectType.stopAcceptingRegistrations(); // Ugly hack :( if (!Main.useConsole) { @@ -565,7 +573,7 @@ public final class CraftServer implements Server { do { for (WorldServer server : console.worlds) { used = server.dimension == dimension; - if (used) { + if (used) { dimension++; break; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index e1e8b20406..12a0deb0ca 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -6,10 +6,13 @@ import net.minecraft.server.EntityEgg; import net.minecraft.server.EntityLiving; import net.minecraft.server.EntitySnowball; import net.minecraft.server.EntityPlayer; +import net.minecraft.server.MobEffect; +import net.minecraft.server.MobEffectList; import org.bukkit.Location; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.potion.CraftPotionEffectType; import org.bukkit.block.Block; import org.bukkit.entity.Arrow; @@ -18,8 +21,11 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Snowball; import org.bukkit.entity.Vehicle; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import org.bukkit.util.BlockIterator; +import java.util.Collection; import java.util.List; import java.util.HashSet; import java.util.ArrayList; @@ -228,4 +234,46 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public Player getKiller() { return getHandle().killer == null ? null : (Player) getHandle().killer.getBukkitEntity(); } + + public boolean addPotionEffect(PotionEffect effect) { + return addPotionEffect(effect, false); + } + + public boolean addPotionEffect(PotionEffect effect, boolean force) { + if (hasPotionEffect(effect.getType())) { + if (!force) { + return false; + } + removePotionEffect(effect.getType()); + } + getHandle().addEffect(new MobEffect(effect.getType().getId(), effect.getDuration(), effect.getAmplifier())); + return true; + } + + public boolean addPotionEffects(Collection effects) { + boolean success = true; + for (PotionEffect effect : effects) { + success &= addPotionEffect(effect); + } + return success; + } + + public boolean hasPotionEffect(PotionEffectType type) { + return getHandle().hasEffect(MobEffectList.byId[type.getId()]); + } + + public void removePotionEffect(PotionEffectType type) { + getHandle().effects.remove(type.getId()); + } + + public Collection getActivePotionEffects() { + List effects = new ArrayList(); + for (Object raw : getHandle().effects.values()) { + if (!(raw instanceof MobEffect)) + continue; + MobEffect handle = (MobEffect) raw; + effects.add(new PotionEffect(PotionEffectType.getById(handle.getEffectId()), handle.getDuration(), handle.getAmplifier())); + } + return effects; + } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java index 81dca041ff..5afda66172 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java @@ -1,14 +1,30 @@ package org.bukkit.craftbukkit.entity; +import java.util.Collection; + import net.minecraft.server.EntityPotion; + import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.ThrownPotion; +import org.bukkit.potion.Potion; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionEffect; public class CraftThrownPotion extends CraftProjectile implements ThrownPotion { + private Collection effects = null; + public CraftThrownPotion(CraftServer server, EntityPotion entity) { super(server, entity); } + public Collection getEffects() { + if (effects == null) { + effects = Potion.getBrewer().getEffectsFromDamage(getHandle().f()); + } + + return effects; + } + @Override public EntityPotion getHandle() { return (EntityPotion) entity; diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java new file mode 100644 index 0000000000..914c5cb384 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java @@ -0,0 +1,47 @@ +package org.bukkit.craftbukkit.potion; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import net.minecraft.server.MobEffect; + +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionBrewer; +import org.bukkit.potion.PotionEffect; + +import com.google.common.collect.Maps; + +public class CraftPotionBrewer implements PotionBrewer { + private static final Map> cache = Maps.newHashMap(); + + public Collection getEffectsFromDamage(int damage) { + if (cache.containsKey(damage)) + return cache.get(damage); + + List mcEffects = net.minecraft.server.PotionBrewer.a(damage, false); + List effects = new ArrayList(); + 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(mcEffect.getEffectId()), + mcEffect.getDuration(), mcEffect.getAmplifier()); + // Minecraft PotionBrewer applies duration modifiers automatically. + effects.add(effect); + } + + cache.put(damage, effects); + + return effects; + } + + public PotionEffect createEffect(PotionEffectType potion, int duration, int amplifier) { + return new PotionEffect(potion, potion.isInstant() ? 1 : (int) (duration * potion.getDurationModifier()), + amplifier); + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java new file mode 100644 index 0000000000..fabd9f72b1 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java @@ -0,0 +1,74 @@ +package org.bukkit.craftbukkit.potion; + +import net.minecraft.server.MobEffectList; + +import org.bukkit.potion.PotionEffectType; + +public class CraftPotionEffectType extends PotionEffectType { + private final MobEffectList handle; + + public CraftPotionEffectType(MobEffectList handle) { + super(handle.id); + this.handle = handle; + } + + @Override + public double getDurationModifier() { + return handle.d(); + } + + public MobEffectList getHandle() { + return handle; + } + + @Override + public String getName() { + switch (handle.id) { + case 1: + return "SPEED"; + case 2: + return "SLOW"; + case 3: + return "FAST_DIGGING"; + case 4: + return "SLOW_DIGGING"; + case 5: + return "INCREASE_DAMAGE"; + case 6: + return "HEAL"; + case 7: + return "HARM"; + case 8: + return "JUMP"; + case 9: + return "CONFUSION"; + case 10: + return "REGENERATION"; + case 11: + return "DAMAGE_RESISTANCE"; + case 12: + return "FIRE_RESISTANCE"; + case 13: + return "WATER_BREATHING"; + case 14: + return "INVISIBILITY"; + case 15: + return "BLINDNESS"; + case 16: + return "NIGHT_VISION"; + case 17: + return "HUNGER"; + case 18: + return "WEAKNESS"; + case 19: + return "POISON"; + default: + return "UNKNOWN_EFFECT_TYPE_" + handle.id; + } + } + + @Override + public boolean isInstant() { + return handle.b(); + } +} diff --git a/src/test/java/org/bukkit/potion/PotionTest.java b/src/test/java/org/bukkit/potion/PotionTest.java new file mode 100644 index 0000000000..edc308f847 --- /dev/null +++ b/src/test/java/org/bukkit/potion/PotionTest.java @@ -0,0 +1,27 @@ +package org.bukkit.potion; + +import static org.junit.Assert.*; + +import org.bukkit.craftbukkit.potion.CraftPotionBrewer; +import org.junit.BeforeClass; +import org.junit.Test; + +import net.minecraft.server.MobEffectList; + +public class PotionTest { + @BeforeClass + public static void setUp() { + Potion.setPotionBrewer(new CraftPotionBrewer()); + MobEffectList.BLINDNESS.getClass(); + PotionEffectType.stopAcceptingRegistrations(); + } + + @Test + public void getEffects() { + for (PotionType type : PotionType.values()) { + for (PotionEffect effect : new Potion(type).getEffects()) { + assertTrue(effect.getType() == PotionEffectType.getById(effect.getType().getId())); + } + } + } +}