package net.minecraft.server;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
// CraftBukkit start
import org.bukkit.Location;
import org.bukkit.event.entity.EntityTeleportEvent;
// CraftBukkit end
public class EntityShulker extends EntityGolem implements IMonster {
private static final UUID by = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F");
private static final AttributeModifier bz = (new AttributeModifier(EntityShulker.by, "Covered armor bonus", 20.0D, 0)).a(false);
protected static final DataWatcherObject<EnumDirection> a = DataWatcher.a(EntityShulker.class, DataWatcherRegistry.l);
protected static final DataWatcherObject<Optional<BlockPosition>> b = DataWatcher.a(EntityShulker.class, DataWatcherRegistry.k);
protected static final DataWatcherObject<Byte> c = DataWatcher.a(EntityShulker.class, DataWatcherRegistry.a);
public static final DataWatcherObject<Byte> bw = DataWatcher.a(EntityShulker.class, DataWatcherRegistry.a); // PAIL: protected -> public, rename COLOR
public static final EnumColor bx = EnumColor.PURPLE;
private float bA;
private float bB;
private BlockPosition bC;
private int bD;
public EntityShulker(World world) {
super(world);
this.setSize(1.0F, 1.0F);
this.aO = 180.0F;
this.aN = 180.0F;
this.fireProof = true;
this.bC = null;
this.b_ = 5;
}
@Override
@Nullable
public GroupDataEntity prepare(DifficultyDamageScaler difficultydamagescaler, @Nullable GroupDataEntity groupdataentity) {
this.aN = 180.0F;
this.aO = 180.0F;
this.yaw = 180.0F;
this.lastYaw = 180.0F;
this.aP = 180.0F;
this.aQ = 180.0F;
return super.prepare(difficultydamagescaler, groupdataentity);
}
@Override
protected void r() {
this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(4, new EntityShulker.a());
this.goalSelector.a(7, new EntityShulker.e(null));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, true, new Class[0]));
this.targetSelector.a(2, new EntityShulker.d(this));
this.targetSelector.a(3, new EntityShulker.c(this));
}
@Override
protected boolean playStepSound() {
return false;
}
@Override
public SoundCategory bC() {
return SoundCategory.HOSTILE;
}
@Override
protected SoundEffect G() {
return SoundEffects.fz;
}
@Override
public void D() {
if (!this.do_()) {
super.D();
}
}
@Override
protected SoundEffect bX() {
return SoundEffects.fF;
}
@Override
protected SoundEffect bW() {
return this.do_() ? SoundEffects.fH : SoundEffects.fG;
}
@Override
protected void i() {
super.i();
this.datawatcher.register(EntityShulker.a, EnumDirection.DOWN);
this.datawatcher.register(EntityShulker.b, Optional.absent());
this.datawatcher.register(EntityShulker.c, Byte.valueOf((byte) 0));
this.datawatcher.register(EntityShulker.bw, Byte.valueOf((byte) EntityShulker.bx.getColorIndex()));
}
@Override
protected void initAttributes() {
super.initAttributes();
this.getAttributeInstance(GenericAttributes.maxHealth).setValue(30.0D);
}
@Override
protected EntityAIBodyControl s() {
return new EntityShulker.b(this);
}
public static void a(DataConverterManager dataconvertermanager) {
EntityInsentient.a(dataconvertermanager, EntityShulker.class);
}
@Override
public void a(NBTTagCompound nbttagcompound) {
super.a(nbttagcompound);
this.datawatcher.set(EntityShulker.a, EnumDirection.fromType1(nbttagcompound.getByte("AttachFace")));
this.datawatcher.set(EntityShulker.c, Byte.valueOf(nbttagcompound.getByte("Peek")));
this.datawatcher.set(EntityShulker.bw, Byte.valueOf(nbttagcompound.getByte("Color")));
if (nbttagcompound.hasKey("APX")) {
int i = nbttagcompound.getInt("APX");
int j = nbttagcompound.getInt("APY");
int k = nbttagcompound.getInt("APZ");
this.datawatcher.set(EntityShulker.b, Optional.of(new BlockPosition(i, j, k)));
} else {
this.datawatcher.set(EntityShulker.b, Optional.<BlockPosition>absent());
}
}
@Override
public void b(NBTTagCompound nbttagcompound) {
super.b(nbttagcompound);
nbttagcompound.setByte("AttachFace", (byte) this.datawatcher.get(EntityShulker.a).a());
nbttagcompound.setByte("Peek", this.datawatcher.get(EntityShulker.c).byteValue());
nbttagcompound.setByte("Color", this.datawatcher.get(EntityShulker.bw).byteValue());
BlockPosition blockposition = this.di();
if (blockposition != null) {
nbttagcompound.setInt("APX", blockposition.getX());
nbttagcompound.setInt("APY", blockposition.getY());
nbttagcompound.setInt("APZ", blockposition.getZ());
}
}
@Override
public void A_() {
super.A_();
BlockPosition blockposition = (BlockPosition) ((Optional) this.datawatcher.get(EntityShulker.b)).orNull();
if (blockposition == null && !this.world.isClientSide) {
blockposition = new BlockPosition(this);
this.datawatcher.set(EntityShulker.b, Optional.of(blockposition));
}
float f;
if (this.isPassenger()) {
blockposition = null;
f = this.bB().yaw;
this.yaw = f;
this.aN = f;
this.aO = f;
this.bD = 0;
} else if (!this.world.isClientSide) {
IBlockData iblockdata = this.world.getType(blockposition);
if (iblockdata.getMaterial() != Material.AIR) {
EnumDirection enumdirection;
if (iblockdata.getBlock() == Blocks.PISTON_EXTENSION) {
enumdirection = iblockdata.get(BlockPiston.FACING);
if (this.world.isEmpty(blockposition.shift(enumdirection))) {
blockposition = blockposition.shift(enumdirection);
this.datawatcher.set(EntityShulker.b, Optional.of(blockposition));
} else {
this.o();
}
} else if (iblockdata.getBlock() == Blocks.PISTON_HEAD) {
enumdirection = iblockdata.get(BlockPistonExtension.FACING);
if (this.world.isEmpty(blockposition.shift(enumdirection))) {
blockposition = blockposition.shift(enumdirection);
this.datawatcher.set(EntityShulker.b, Optional.of(blockposition));
} else {
this.o();
}
} else {
this.o();
}
}
BlockPosition blockposition1 = blockposition.shift(this.dh());
if (!this.world.d(blockposition1, false)) {
boolean flag = false;
EnumDirection[] aenumdirection = EnumDirection.values();
int i = aenumdirection.length;
for (int j = 0; j < i; ++j) {
EnumDirection enumdirection1 = aenumdirection[j];
blockposition1 = blockposition.shift(enumdirection1);
if (this.world.d(blockposition1, false)) {
this.datawatcher.set(EntityShulker.a, enumdirection1);
flag = true;
break;
}
}
if (!flag) {
this.o();
}
}
BlockPosition blockposition2 = blockposition.shift(this.dh().opposite());
if (this.world.d(blockposition2, false)) {
this.o();
}
}
f = this.dj() * 0.01F;
this.bA = this.bB;
if (this.bB > f) {
this.bB = MathHelper.a(this.bB - 0.05F, f, 1.0F);
} else if (this.bB < f) {
this.bB = MathHelper.a(this.bB + 0.05F, 0.0F, f);
}
if (blockposition != null) {
if (this.world.isClientSide) {
if (this.bD > 0 && this.bC != null) {
--this.bD;
} else {
this.bC = blockposition;
}
}
this.locX = blockposition.getX() + 0.5D;
this.locY = blockposition.getY();
this.locZ = blockposition.getZ() + 0.5D;
this.lastX = this.locX;
this.lastY = this.locY;
this.lastZ = this.locZ;
this.M = this.locX;
this.N = this.locY;
this.O = this.locZ;
double d0 = 0.5D - MathHelper.sin((0.5F + this.bB) * 3.1415927F) * 0.5D;
double d1 = 0.5D - MathHelper.sin((0.5F + this.bA) * 3.1415927F) * 0.5D;
double d2 = d0 - d1;
double d3 = 0.0D;
double d4 = 0.0D;
double d5 = 0.0D;
EnumDirection enumdirection2 = this.dh();
switch (enumdirection2) {
case DOWN:
this.a(new AxisAlignedBB(this.locX - 0.5D, this.locY, this.locZ - 0.5D, this.locX + 0.5D, this.locY + 1.0D + d0, this.locZ + 0.5D));
d4 = d2;
break;
case UP:
this.a(new AxisAlignedBB(this.locX - 0.5D, this.locY - d0, this.locZ - 0.5D, this.locX + 0.5D, this.locY + 1.0D, this.locZ + 0.5D));
d4 = -d2;
break;
case NORTH:
this.a(new AxisAlignedBB(this.locX - 0.5D, this.locY, this.locZ - 0.5D, this.locX + 0.5D, this.locY + 1.0D, this.locZ + 0.5D + d0));
d5 = d2;
break;
case SOUTH:
this.a(new AxisAlignedBB(this.locX - 0.5D, this.locY, this.locZ - 0.5D - d0, this.locX + 0.5D, this.locY + 1.0D, this.locZ + 0.5D));
d5 = -d2;
break;
case WEST:
this.a(new AxisAlignedBB(this.locX - 0.5D, this.locY, this.locZ - 0.5D, this.locX + 0.5D + d0, this.locY + 1.0D, this.locZ + 0.5D));
d3 = d2;
break;
case EAST:
this.a(new AxisAlignedBB(this.locX - 0.5D - d0, this.locY, this.locZ - 0.5D, this.locX + 0.5D, this.locY + 1.0D, this.locZ + 0.5D));
d3 = -d2;
}
if (d2 > 0.0D) {
List list = this.world.getEntities(this, this.getBoundingBox());
if (!list.isEmpty()) {
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
if (!(entity instanceof EntityShulker) && !entity.noclip) {
entity.move(EnumMoveType.SHULKER, d3, d4, d5);
}
}
}
}
}
}
@Override
public void move(EnumMoveType enummovetype, double d0, double d1, double d2) {
if (enummovetype == EnumMoveType.SHULKER_BOX) {
this.o();
} else {
super.move(enummovetype, d0, d1, d2);
}
}
@Override
public void setPosition(double d0, double d1, double d2) {
super.setPosition(d0, d1, d2);
if (this.datawatcher != null && this.ticksLived != 0) {
Optional optional = this.datawatcher.get(EntityShulker.b);
Optional optional1 = Optional.of(new BlockPosition(d0, d1, d2));
if (!optional1.equals(optional)) {
this.datawatcher.set(EntityShulker.b, optional1);
this.datawatcher.set(EntityShulker.c, Byte.valueOf((byte) 0));
this.impulse = true;
}
}
}
protected boolean o() {
if (!this.hasAI() && this.isAlive()) {
BlockPosition blockposition = new BlockPosition(this);
for (int i = 0; i < 5; ++i) {
BlockPosition blockposition1 = blockposition.a(8 - this.random.nextInt(17), 8 - this.random.nextInt(17), 8 - this.random.nextInt(17));
if (blockposition1.getY() > 0 && this.world.isEmpty(blockposition1) && this.world.g(this) && this.world.getCubes(this, new AxisAlignedBB(blockposition1)).isEmpty()) {
boolean flag = false;
EnumDirection[] aenumdirection = EnumDirection.values();
int j = aenumdirection.length;
for (int k = 0; k < j; ++k) {
EnumDirection enumdirection = aenumdirection[k];
if (this.world.d(blockposition1.shift(enumdirection), false)) {
// CraftBukkit start
EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), this.getBukkitEntity().getLocation(), new Location(this.world.getWorld(), blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()));
this.world.getServer().getPluginManager().callEvent(teleport);
if (!teleport.isCancelled()) {
Location to = teleport.getTo();
blockposition1 = new BlockPosition(to.getX(), to.getY(), to.getZ());
this.datawatcher.set(EntityShulker.a, enumdirection);
flag = true;
}
// CraftBukkit end
break;
}
}
if (flag) {
this.a(SoundEffects.fK, 1.0F, 1.0F);
this.datawatcher.set(EntityShulker.b, Optional.of(blockposition1));
this.datawatcher.set(EntityShulker.c, Byte.valueOf((byte) 0));
this.setGoalTarget((EntityLiving) null);
return true;
}
}
}
return false;
} else {
return true;
}
}
@Override
public void n() {
super.n();
this.motX = 0.0D;
this.motY = 0.0D;
this.motZ = 0.0D;
this.aO = 180.0F;
this.aN = 180.0F;
this.yaw = 180.0F;
}
@Override
public void a(DataWatcherObject<?> datawatcherobject) {
if (EntityShulker.b.equals(datawatcherobject) && this.world.isClientSide && !this.isPassenger()) {
BlockPosition blockposition = this.di();
if (blockposition != null) {
if (this.bC == null) {
this.bC = blockposition;
} else {
this.bD = 6;
}
this.locX = blockposition.getX() + 0.5D;
this.locY = blockposition.getY();
this.locZ = blockposition.getZ() + 0.5D;
this.lastX = this.locX;
this.lastY = this.locY;
this.lastZ = this.locZ;
this.M = this.locX;
this.N = this.locY;
this.O = this.locZ;
}
}
super.a(datawatcherobject);
}
@Override
public boolean damageEntity(DamageSource damagesource, float f) {
if (this.do_()) {
Entity entity = damagesource.i();
if (entity instanceof EntityArrow) {
return false;
}
}
if (super.damageEntity(damagesource, f)) {
if (this.getHealth() < this.getMaxHealth() * 0.5D && this.random.nextInt(4) == 0) {
this.o();
}
return true;
} else {
return false;
}
}
private boolean do_() {
return this.dj() == 0;
}
@Override
@Nullable
public AxisAlignedBB ag() {
return this.isAlive() ? this.getBoundingBox() : null;
}
public EnumDirection dh() {
return this.datawatcher.get(EntityShulker.a);
}
@Nullable
public BlockPosition di() {
return (BlockPosition) ((Optional) this.datawatcher.get(EntityShulker.b)).orNull();
}
public void g(@Nullable BlockPosition blockposition) {
this.datawatcher.set(EntityShulker.b, Optional.fromNullable(blockposition));
}
public int dj() {
return this.datawatcher.get(EntityShulker.c).byteValue();
}
public void a(int i) {
if (!this.world.isClientSide) {
this.getAttributeInstance(GenericAttributes.g).c(EntityShulker.bz);
if (i == 0) {
this.getAttributeInstance(GenericAttributes.g).b(EntityShulker.bz);
this.a(SoundEffects.fE, 1.0F, 1.0F);
} else {
this.a(SoundEffects.fI, 1.0F, 1.0F);
}
}
this.datawatcher.set(EntityShulker.c, Byte.valueOf((byte) i));
}
@Override
public float getHeadHeight() {
return 0.5F;
}
@Override
public int N() {
return 180;
}
@Override
public int cL() {
return 180;
}
@Override
public void collide(Entity entity) {}
@Override
public float aA() {
return 0.0F;
}
@Override
@Nullable
protected MinecraftKey J() {
return LootTables.z;
}
static class c extends PathfinderGoalNearestAttackableTarget<EntityLiving> {
public c(EntityShulker entityshulker) {
super(entityshulker, EntityLiving.class, 10, true, false, new Predicate() {
public boolean a(@Nullable EntityLiving entityliving) {
return entityliving instanceof IMonster;
}
@Override
public boolean apply(@Nullable Object object) {
return this.a((EntityLiving) object);
}
});
}
@Override
public boolean a() {
return this.e.aQ() == null ? false : super.a();
}
@Override
protected AxisAlignedBB a(double d0) {
EnumDirection enumdirection = ((EntityShulker) this.e).dh();
return enumdirection.k() == EnumDirection.EnumAxis.X ? this.e.getBoundingBox().grow(4.0D, d0, d0) : (enumdirection.k() == EnumDirection.EnumAxis.Z ? this.e.getBoundingBox().grow(d0, d0, 4.0D) : this.e.getBoundingBox().grow(d0, 4.0D, d0));
}
}
class d extends PathfinderGoalNearestAttackableTarget<EntityHuman> {
public d(EntityShulker entityshulker) {
super(entityshulker, EntityHuman.class, true);
}
@Override
public boolean a() {
return EntityShulker.this.world.getDifficulty() == EnumDifficulty.PEACEFUL ? false : super.a();
}
@Override
protected AxisAlignedBB a(double d0) {
EnumDirection enumdirection = ((EntityShulker) this.e).dh();
return enumdirection.k() == EnumDirection.EnumAxis.X ? this.e.getBoundingBox().grow(4.0D, d0, d0) : (enumdirection.k() == EnumDirection.EnumAxis.Z ? this.e.getBoundingBox().grow(d0, d0, 4.0D) : this.e.getBoundingBox().grow(d0, 4.0D, d0));
}
}
class a extends PathfinderGoal {
private int b;
public a() {
this.a(3);
}
@Override
public boolean a() {
EntityLiving entityliving = EntityShulker.this.getGoalTarget();
return entityliving != null && entityliving.isAlive() ? EntityShulker.this.world.getDifficulty() != EnumDifficulty.PEACEFUL : false;
}
@Override
public void c() {
this.b = 20;
EntityShulker.this.a(100);
}
@Override
public void d() {
EntityShulker.this.a(0);
}
@Override
public void e() {
if (EntityShulker.this.world.getDifficulty() != EnumDifficulty.PEACEFUL) {
--this.b;
EntityLiving entityliving = EntityShulker.this.getGoalTarget();
EntityShulker.this.getControllerLook().a(entityliving, 180.0F, 180.0F);
double d0 = EntityShulker.this.h(entityliving);
if (d0 < 400.0D) {
if (this.b <= 0) {
this.b = 20 + EntityShulker.this.random.nextInt(10) * 20 / 2;
EntityShulkerBullet entityshulkerbullet = new EntityShulkerBullet(EntityShulker.this.world, EntityShulker.this, entityliving, EntityShulker.this.dh().k());
EntityShulker.this.world.addEntity(entityshulkerbullet);
EntityShulker.this.a(SoundEffects.fJ, 2.0F, (EntityShulker.this.random.nextFloat() - EntityShulker.this.random.nextFloat()) * 0.2F + 1.0F);
}
} else {
EntityShulker.this.setGoalTarget((EntityLiving) null);
}
super.e();
}
}
}
class e extends PathfinderGoal {
private int b;
private e() {}
@Override
public boolean a() {
return EntityShulker.this.getGoalTarget() == null && EntityShulker.this.random.nextInt(40) == 0;
}
@Override
public boolean b() {
return EntityShulker.this.getGoalTarget() == null && this.b > 0;
}
@Override
public void c() {
this.b = 20 * (1 + EntityShulker.this.random.nextInt(3));
EntityShulker.this.a(30);
}
@Override
public void d() {
if (EntityShulker.this.getGoalTarget() == null) {
EntityShulker.this.a(0);
}
}
@Override
public void e() {
--this.b;
}
e(Object object) {
this();
}
}
class b extends EntityAIBodyControl {
public b(EntityLiving entityliving) {
super(entityliving);
}
@Override
public void a() {}
}
}