package com.laytonsmith.abstraction.bukkit.entities;
import com.laytonsmith.PureUtilities.Common.ReflectionUtils;
import com.laytonsmith.abstraction.MCEntity;
import com.laytonsmith.abstraction.MCEntityEquipment;
import com.laytonsmith.abstraction.MCLivingEntity;
import com.laytonsmith.abstraction.MCLocation;
import com.laytonsmith.abstraction.MCPlayer;
import com.laytonsmith.abstraction.blocks.MCBlock;
import com.laytonsmith.abstraction.bukkit.BukkitConvertor;
import com.laytonsmith.abstraction.bukkit.BukkitMCEntityEquipment;
import com.laytonsmith.abstraction.bukkit.BukkitMCLocation;
import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCBlock;
import com.laytonsmith.abstraction.enums.MCVersion;
import com.laytonsmith.core.Static;
import com.laytonsmith.core.constructs.Target;
import com.laytonsmith.core.exceptions.CRE.CREBadEntityException;
import org.bukkit.block.Block;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.BlockIterator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
*
*/
public class BukkitMCLivingEntity extends BukkitMCEntityProjectileSource implements MCLivingEntity {
LivingEntity le;
public BukkitMCLivingEntity(Entity ent) {
super(ent);
this.le = (LivingEntity) ent;
}
@Override
public double getHealth() {
return le.getHealth();
}
@Override
public void setHealth(double i) {
le.setHealth(i);
}
@Override
public double getMaxHealth() {
return le.getMaxHealth();
}
@Override
public void setMaxHealth(double health) {
le.setMaxHealth(health);
}
@Override
public void resetMaxHealth() {
le.resetMaxHealth();
}
@Override
public void damage(double i) {
le.damage(i);
}
@Override
public void damage(double amount, MCEntity source) {
le.damage(amount, ((BukkitMCEntity) source).getHandle());
}
@Override
public double getEyeHeight() {
return le.getEyeHeight();
}
@Override
public double getEyeHeight(boolean ignoreSneaking) {
return le.getEyeHeight(ignoreSneaking);
}
@Override
public MCLocation getEyeLocation() {
return new BukkitMCLocation(le.getEyeLocation());
}
@Override
public MCPlayer getKiller() {
return new BukkitMCPlayer(le.getKiller());
}
@Override
public double getLastDamage() {
return le.getLastDamage();
}
@Override
public List<MCBlock> getLastTwoTargetBlocks(HashSet<Byte> transparent,
int maxDistance) {
List<Block> lst = le.getLastTwoTargetBlocks(transparent, maxDistance);
List<MCBlock> retn = new ArrayList<MCBlock>();
for (Block b : lst) {
retn.add(new BukkitMCBlock(b));
}
return retn;
}
@Override
public List<MCBlock> getLineOfSight(HashSet<Byte> transparent,
int maxDistance) {
List<Block> lst = le.getLineOfSight(transparent, maxDistance);
List<MCBlock> retn = new ArrayList<MCBlock>();
for (Block b : lst) {
retn.add(new BukkitMCBlock(b));
}
return retn;
}
@Override
public boolean hasLineOfSight(MCEntity other) {
return le.hasLineOfSight(((BukkitMCEntity) other).getHandle());
}
@Override
public int getMaximumAir() {
return le.getMaximumAir();
}
@Override
public int getMaximumNoDamageTicks() {
return le.getMaximumNoDamageTicks();
}
@Override
public int getNoDamageTicks() {
return le.getNoDamageTicks();
}
@Override
public int getRemainingAir() {
return le.getRemainingAir();
}
@Override
public MCBlock getTargetBlock(HashSet<Byte> b, int i) {
return new BukkitMCBlock(le.getTargetBlock(b, i));
}
@Override
public MCBlock getTargetBlock(HashSet<Short> b, int i, boolean castToByte) {
if (castToByte) {
if (b == null) {
return getTargetBlock(null, i);
}
HashSet<Byte> bb = new HashSet<Byte>();
for (int id : b) {
bb.add((byte) id);
}
return getTargetBlock(bb, i);
}
return new BukkitMCBlock(getFirstTargetBlock(b, i));
}
private Block getFirstTargetBlock(HashSet<Short> transparent, int maxDistance) {
List<Block> blocks = getLineOfSight(transparent, maxDistance, 1);
return blocks.get(0);
}
private List<Block> getLineOfSight(HashSet<Short> transparent, int maxDistance, int maxLength) {
if (maxDistance > 512) {
maxDistance = 512;
}
ArrayList<Block> blocks = new ArrayList<Block>();
Iterator<Block> itr = new BlockIterator(le, maxDistance);
while (itr.hasNext()) {
Block block = itr.next();
blocks.add(block);
if (maxLength != 0 && blocks.size() > maxLength) {
blocks.remove(0);
}
int id = block.getTypeId();
if (transparent == null) {
if (id != 0) {
break;
}
} else {
if (!transparent.contains((short) id)) {
break;
}
}
}
return blocks;
}
@Override
public boolean hasAI() {
try {
return le.hasAI();
} catch(NoSuchMethodError ex){
// Probably before 1.9.2
return true;
}
}
/**
* @param potionID - ID of the potion
* @param strength - potion strength
* @param seconds - duration of the potion in seconds
* @param ambient - make particles less noticable
* @param particles - enable or disable particles entirely
* @param t - target
*/
@Override
public void addEffect(int potionID, int strength, int seconds, boolean ambient, boolean particles, Target t) {
PotionEffect pe;
if (Static.getServer().getMinecraftVersion().lt(MCVersion.MC1_8)) {
pe = new PotionEffect(PotionEffectType.getById(potionID), seconds * 20, strength, ambient);
} else {
pe = new PotionEffect(PotionEffectType.getById(potionID), seconds * 20, strength, ambient, particles);
}
try{
if(le != null){
le.addPotionEffect(pe, true);
}
} catch(NullPointerException e){
Logger.getLogger(BukkitMCLivingEntity.class.getName()).log(Level.SEVERE,
"Bukkit appears to have derped. This is a problem with Bukkit, not CommandHelper. The effect should have still been applied.", e);
}
}
@Override
public int getMaxEffect(){
try {
PotionEffectType[] arr = (PotionEffectType[])ReflectionUtils.get(PotionEffectType.class, "byId");
return arr.length - 1;
} catch(ReflectionUtils.ReflectionException e){
return Integer.MAX_VALUE;
}
}
@Override
public boolean removeEffect(int potionID) {
PotionEffectType t = PotionEffectType.getById(potionID);
boolean hasIt = false;
for(PotionEffect pe : le.getActivePotionEffects()) {
if (pe.getType() == t) {
hasIt = true;
break;
}
}
le.removePotionEffect(t);
return hasIt;
}
@Override
public List<MCEffect> getEffects(){
List<MCEffect> effects = new ArrayList<MCEffect>();
for(PotionEffect pe : le.getActivePotionEffects()){
MCEffect e;
if (Static.getServer().getMinecraftVersion().lt(MCVersion.MC1_8)) {
e = new MCEffect(pe.getType().getId(), pe.getAmplifier(),
pe.getDuration() / 20, pe.isAmbient(), true);
} else {
e = new MCEffect(pe.getType().getId(), pe.getAmplifier(),
pe.getDuration() / 20, pe.isAmbient(), pe.hasParticles());
}
effects.add(e);
}
return effects;
}
@Override
public void setLastDamage(double damage) {
le.setLastDamage(damage);
}
@Override
public void setMaximumAir(int ticks) {
le.setMaximumAir(ticks);
}
@Override
public void setMaximumNoDamageTicks(int ticks) {
le.setMaximumNoDamageTicks(ticks);
}
@Override
public void setNoDamageTicks(int ticks) {
le.setNoDamageTicks(ticks);
}
@Override
public void setRemainingAir(int ticks) {
le.setRemainingAir(ticks);
}
public LivingEntity asLivingEntity() {
return le;
}
@Override
public MCEntityEquipment getEquipment() {
if (le.getEquipment() == null) {
return null;
}
return new BukkitMCEntityEquipment(le.getEquipment());
}
@Override
public boolean getCanPickupItems() {
return le.getCanPickupItems();
}
@Override
public void setCanPickupItems(boolean pickup) {
le.setCanPickupItems(pickup);
}
@Override
public boolean getRemoveWhenFarAway() {
return le.getRemoveWhenFarAway();
}
@Override
public void setRemoveWhenFarAway(boolean remove) {
le.setRemoveWhenFarAway(remove);
}
@Override
public MCLivingEntity getTarget(Target t) {
if (!(le instanceof Creature)) {
throw new CREBadEntityException("This type of mob does not have a target API", t);
}
LivingEntity target = ((Creature) le).getTarget();
return target == null ? null : new BukkitMCLivingEntity(target);
}
@Override
public void setTarget(MCLivingEntity target, Target t) {
if (!(le instanceof Creature)) {
throw new CREBadEntityException("This type of mob does not have a target API", t);
}
((Creature) le).setTarget(target == null ? null : ((BukkitMCLivingEntity) target).asLivingEntity());
}
@Override
public void kill(){
le.setLastDamageCause(new EntityDamageEvent(le, EntityDamageEvent.DamageCause.CUSTOM, le.getHealth()));
le.setHealth(0D);
}
@Override
public MCEntity getLeashHolder() {
return le.isLeashed() ? BukkitConvertor.BukkitGetCorrectEntity(le.getLeashHolder()) : null;
}
@Override
public boolean isLeashed() {
return le.isLeashed();
}
@Override
public void setLeashHolder(MCEntity holder) {
le.setLeashHolder(holder == null ? null : ((BukkitMCEntity) holder).getHandle());
}
@Override
public boolean isGliding() {
try {
return le.isGliding();
} catch(NoSuchMethodError ex){
// Probably before 1.9
return false;
}
}
@Override
public void setGliding(Boolean glide) {
try {
le.setGliding(glide);
} catch(NoSuchMethodError ex){
// Probably before 1.9
}
}
@Override
public void setAI(Boolean ai) {
try {
le.setAI(ai);
} catch(NoSuchMethodError ex){
// Probably before 1.9.2
}
}
}