package net.minecraft.server;
import com.google.common.collect.Maps;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import javax.annotation.Nullable;
// CraftBukkit start
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.craftbukkit.entity.CraftLivingEntity;
import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.entity.EntityUnleashEvent;
import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason;
// CraftBukkit end
public abstract class EntityInsentient extends EntityLiving {
private static final DataWatcherObject<Byte> a = DataWatcher.a(EntityInsentient.class, DataWatcherRegistry.a);
public int a_;
protected int b_;
private final ControllerLook lookController;
protected ControllerMove moveController;
protected ControllerJump g;
private final EntityAIBodyControl c;
protected NavigationAbstract navigation;
public PathfinderGoalSelector goalSelector;
public PathfinderGoalSelector targetSelector;
private EntityLiving goalTarget;
private final EntitySenses bv;
private final NonNullList<ItemStack> bw;
public float[] dropChanceHand;
private final NonNullList<ItemStack> bx;
public float[] dropChanceArmor;
public boolean canPickUpLoot;
public boolean persistent;
private final Map<PathType, Float> bA;
private MinecraftKey bB;
private long bC;
private boolean bD;
private Entity leashHolder;
private NBTTagCompound bF;
public PathfinderGoalFloat goalFloat; // Paper
public EntityInsentient(World world) {
super(world);
this.bw = NonNullList.a(2, ItemStack.a);
this.dropChanceHand = new float[2];
this.bx = NonNullList.a(4, ItemStack.a);
this.dropChanceArmor = new float[4];
this.bA = Maps.newEnumMap(PathType.class);
this.goalSelector = new PathfinderGoalSelector(world != null && world.methodProfiler != null ? world.methodProfiler : null);
this.targetSelector = new PathfinderGoalSelector(world != null && world.methodProfiler != null ? world.methodProfiler : null);
this.lookController = new ControllerLook(this);
this.moveController = new ControllerMove(this);
this.g = new ControllerJump(this);
this.c = this.s();
this.navigation = this.b(world);
this.bv = new EntitySenses(this);
Arrays.fill(this.dropChanceArmor, 0.085F);
Arrays.fill(this.dropChanceHand, 0.085F);
if (world != null && !world.isClientSide) {
this.r();
}
// CraftBukkit start - default persistance to type's persistance value
this.persistent = !isTypeNotPersistent();
// CraftBukkit end
}
protected void r() {}
@Override
protected void initAttributes() {
super.initAttributes();
this.getAttributeMap().b(GenericAttributes.FOLLOW_RANGE).setValue(16.0D);
}
protected NavigationAbstract b(World world) {
return new Navigation(this, world);
}
public float a(PathType pathtype) {
Float ofloat = this.bA.get(pathtype);
return ofloat == null ? pathtype.a() : ofloat.floatValue();
}
public void a(PathType pathtype, float f) {
this.bA.put(pathtype, Float.valueOf(f));
}
protected EntityAIBodyControl s() {
return new EntityAIBodyControl(this);
}
public ControllerLook getControllerLook() {
return this.lookController;
}
public ControllerMove getControllerMove() {
return this.moveController;
}
public ControllerJump getControllerJump() {
return this.g;
}
public NavigationAbstract getNavigation() {
return this.navigation;
}
public EntitySenses getEntitySenses() {
return this.bv;
}
@Nullable
public EntityLiving getGoalTarget() {
return this.goalTarget;
}
public void setGoalTarget(@Nullable EntityLiving entityliving) {
// CraftBukkit start - fire event
setGoalTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true);
}
public boolean setGoalTarget(EntityLiving entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) {
if (getGoalTarget() == entityliving) return false;
if (fireEvent) {
if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getGoalTarget() != null && entityliving == null) {
reason = getGoalTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED;
}
if (reason == EntityTargetEvent.TargetReason.UNKNOWN) {
world.getServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception());
}
CraftLivingEntity ctarget = null;
if (entityliving != null) {
ctarget = (CraftLivingEntity) entityliving.getBukkitEntity();
}
EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason);
world.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return false;
}
if (event.getTarget() != null) {
entityliving = ((CraftLivingEntity) event.getTarget()).getHandle();
} else {
entityliving = null;
}
}
this.goalTarget = entityliving;
return true;
// CraftBukkit end
}
public boolean d(Class<? extends EntityLiving> oclass) {
return oclass != EntityGhast.class;
}
public void A() {}
@Override
protected void i() {
super.i();
this.datawatcher.register(EntityInsentient.a, Byte.valueOf((byte) 0));
}
public int C() {
return 80;
}
public void D() {
SoundEffect soundeffect = this.G();
if (soundeffect != null) {
this.a(soundeffect, this.ci(), this.cj());
}
}
@Override
public void U() {
super.U();
this.world.methodProfiler.a("mobBaseTick");
if (this.isAlive() && this.random.nextInt(1000) < this.a_++) {
this.o();
this.D();
}
}
@Override
protected void c(DamageSource damagesource) {
this.o();
super.c(damagesource);
}
private void o() {
this.a_ = -this.C();
}
@Override
protected int getExpValue(EntityHuman entityhuman) {
if (this.b_ > 0) {
int i = this.b_;
int j;
for (j = 0; j < this.bx.size(); ++j) {
if (!this.bx.get(j).isEmpty() && this.dropChanceArmor[j] <= 1.0F) {
i += 1 + this.random.nextInt(3);
}
}
for (j = 0; j < this.bw.size(); ++j) {
if (!this.bw.get(j).isEmpty() && this.dropChanceHand[j] <= 1.0F) {
i += 1 + this.random.nextInt(3);
}
}
return i;
} else {
return this.b_;
}
}
public void doSpawnEffect() {
if (this.world.isClientSide) {
for (int i = 0; i < 20; ++i) {
double d0 = this.random.nextGaussian() * 0.02D;
double d1 = this.random.nextGaussian() * 0.02D;
double d2 = this.random.nextGaussian() * 0.02D;
double d3 = 10.0D;
this.world.addParticle(EnumParticle.EXPLOSION_NORMAL, this.locX + this.random.nextFloat() * this.width * 2.0F - this.width - d0 * 10.0D, this.locY + this.random.nextFloat() * this.length - d1 * 10.0D, this.locZ + this.random.nextFloat() * this.width * 2.0F - this.width - d2 * 10.0D, d0, d1, d2, new int[0]);
}
} else {
this.world.broadcastEntityEffect(this, (byte) 20);
}
}
@Override
public void A_() {
super.A_();
if (!this.world.isClientSide) {
this.cV();
if (this.ticksLived % 5 == 0) {
boolean flag = !(this.bw() instanceof EntityInsentient);
boolean flag1 = !(this.bB() instanceof EntityBoat);
this.goalSelector.a(1, flag);
this.goalSelector.a(4, flag && flag1);
this.goalSelector.a(2, flag);
}
}
}
@Override
protected float h(float f, float f1) {
this.c.a();
return f1;
}
@Nullable
protected SoundEffect G() {
return null;
}
@Nullable
protected Item getLoot() {
return null;
}
@Override
protected void dropDeathLoot(boolean flag, int i) {
Item item = this.getLoot();
if (item != null) {
int j = this.random.nextInt(3);
if (i > 0) {
j += this.random.nextInt(i + 1);
}
for (int k = 0; k < j; ++k) {
this.a(item, 1);
}
}
}
public static void a(DataConverterManager dataconvertermanager, Class<?> oclass) {
dataconvertermanager.a(DataConverterTypes.ENTITY, (new DataInspectorItemList(oclass, new String[] { "ArmorItems", "HandItems"})));
}
@Override
public void b(NBTTagCompound nbttagcompound) {
super.b(nbttagcompound);
nbttagcompound.setBoolean("CanPickUpLoot", this.cT());
nbttagcompound.setBoolean("PersistenceRequired", this.persistent);
NBTTagList nbttaglist = new NBTTagList();
NBTTagCompound nbttagcompound1;
for (Iterator iterator = this.bx.iterator(); iterator.hasNext(); nbttaglist.add(nbttagcompound1)) {
ItemStack itemstack = (ItemStack) iterator.next();
nbttagcompound1 = new NBTTagCompound();
if (!itemstack.isEmpty()) {
itemstack.save(nbttagcompound1);
}
}
nbttagcompound.set("ArmorItems", nbttaglist);
NBTTagList nbttaglist1 = new NBTTagList();
NBTTagCompound nbttagcompound2;
for (Iterator iterator1 = this.bw.iterator(); iterator1.hasNext(); nbttaglist1.add(nbttagcompound2)) {
ItemStack itemstack1 = (ItemStack) iterator1.next();
nbttagcompound2 = new NBTTagCompound();
if (!itemstack1.isEmpty()) {
itemstack1.save(nbttagcompound2);
}
}
nbttagcompound.set("HandItems", nbttaglist1);
NBTTagList nbttaglist2 = new NBTTagList();
float[] afloat = this.dropChanceArmor;
int i = afloat.length;
int j;
for (j = 0; j < i; ++j) {
float f = afloat[j];
nbttaglist2.add(new NBTTagFloat(f));
}
nbttagcompound.set("ArmorDropChances", nbttaglist2);
NBTTagList nbttaglist3 = new NBTTagList();
float[] afloat1 = this.dropChanceHand;
j = afloat1.length;
for (int k = 0; k < j; ++k) {
float f1 = afloat1[k];
nbttaglist3.add(new NBTTagFloat(f1));
}
nbttagcompound.set("HandDropChances", nbttaglist3);
nbttagcompound.setBoolean("Leashed", this.bD);
if (this.leashHolder != null) {
nbttagcompound2 = new NBTTagCompound();
if (this.leashHolder instanceof EntityLiving) {
UUID uuid = this.leashHolder.getUniqueID();
nbttagcompound2.a("UUID", uuid);
} else if (this.leashHolder instanceof EntityHanging) {
BlockPosition blockposition = ((EntityHanging) this.leashHolder).getBlockPosition();
nbttagcompound2.setInt("X", blockposition.getX());
nbttagcompound2.setInt("Y", blockposition.getY());
nbttagcompound2.setInt("Z", blockposition.getZ());
}
nbttagcompound.set("Leash", nbttagcompound2);
}
nbttagcompound.setBoolean("LeftHanded", this.cZ());
if (this.bB != null) {
nbttagcompound.setString("DeathLootTable", this.bB.toString());
if (this.bC != 0L) {
nbttagcompound.setLong("DeathLootTableSeed", this.bC);
}
}
if (this.hasAI()) {
nbttagcompound.setBoolean("NoAI", this.hasAI());
}
}
@Override
public void a(NBTTagCompound nbttagcompound) {
super.a(nbttagcompound);
// CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
if (nbttagcompound.hasKeyOfType("CanPickUpLoot", 1)) {
boolean data = nbttagcompound.getBoolean("CanPickUpLoot");
if (isLevelAtLeast(nbttagcompound, 1) || data) {
this.m(data);
}
}
boolean data = nbttagcompound.getBoolean("PersistenceRequired");
if (isLevelAtLeast(nbttagcompound, 1) || data) {
this.persistent = data;
}
// CraftBukkit end
NBTTagList nbttaglist;
int i;
if (nbttagcompound.hasKeyOfType("ArmorItems", 9)) {
nbttaglist = nbttagcompound.getList("ArmorItems", 10);
for (i = 0; i < this.bx.size(); ++i) {
this.bx.set(i, new ItemStack(nbttaglist.get(i)));
}
}
if (nbttagcompound.hasKeyOfType("HandItems", 9)) {
nbttaglist = nbttagcompound.getList("HandItems", 10);
for (i = 0; i < this.bw.size(); ++i) {
this.bw.set(i, new ItemStack(nbttaglist.get(i)));
}
}
if (nbttagcompound.hasKeyOfType("ArmorDropChances", 9)) {
nbttaglist = nbttagcompound.getList("ArmorDropChances", 5);
for (i = 0; i < nbttaglist.size(); ++i) {
this.dropChanceArmor[i] = nbttaglist.f(i);
}
}
if (nbttagcompound.hasKeyOfType("HandDropChances", 9)) {
nbttaglist = nbttagcompound.getList("HandDropChances", 5);
for (i = 0; i < nbttaglist.size(); ++i) {
this.dropChanceHand[i] = nbttaglist.f(i);
}
}
this.bD = nbttagcompound.getBoolean("Leashed");
if (this.bD && nbttagcompound.hasKeyOfType("Leash", 10)) {
this.bF = nbttagcompound.getCompound("Leash");
}
this.o(nbttagcompound.getBoolean("LeftHanded"));
if (nbttagcompound.hasKeyOfType("DeathLootTable", 8)) {
this.bB = new MinecraftKey(nbttagcompound.getString("DeathLootTable"));
this.bC = nbttagcompound.getLong("DeathLootTableSeed");
}
this.setAI(nbttagcompound.getBoolean("NoAI"));
}
@Nullable
protected MinecraftKey J() {
return null;
}
@Override
protected void a(boolean flag, int i, DamageSource damagesource) {
MinecraftKey minecraftkey = this.bB;
if (minecraftkey == null) {
minecraftkey = this.J();
}
if (minecraftkey != null) {
LootTable loottable = this.world.ak().a(minecraftkey);
this.bB = null;
LootTableInfo.a loottableinfo_a = (new LootTableInfo.a((WorldServer) this.world)).a(this).a(damagesource);
if (flag && this.killer != null) {
loottableinfo_a = loottableinfo_a.a(this.killer).a(this.killer.dj());
}
List list = loottable.a(this.bC == 0L ? this.random : new Random(this.bC), loottableinfo_a.a());
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
ItemStack itemstack = (ItemStack) iterator.next();
this.a(itemstack, 0.0F);
}
this.dropEquipment(flag, i);
} else {
super.a(flag, i, damagesource);
}
}
public void o(float f) {
this.bf = f;
}
public void p(float f) {
this.be = f;
}
@Override
public void l(float f) {
super.l(f);
this.o(f);
}
@Override
public void n() {
super.n();
this.world.methodProfiler.a("looting");
if (!this.world.isClientSide && this.cT() && !this.aU && this.world.getGameRules().getBoolean("mobGriefing")) {
List list = this.world.a(EntityItem.class, this.getBoundingBox().grow(1.0D, 0.0D, 1.0D));
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
EntityItem entityitem = (EntityItem) iterator.next();
if (!entityitem.dead && !entityitem.getItemStack().isEmpty() && !entityitem.t()) {
this.a(entityitem);
}
}
}
}
protected void a(EntityItem entityitem) {
ItemStack itemstack = entityitem.getItemStack();
EnumItemSlot enumitemslot = d(itemstack);
boolean flag = true;
ItemStack itemstack1 = this.getEquipment(enumitemslot);
if (!itemstack1.isEmpty()) {
if (enumitemslot.a() == EnumItemSlot.Function.HAND) {
if (itemstack.getItem() instanceof ItemSword && !(itemstack1.getItem() instanceof ItemSword)) {
flag = true;
} else if (itemstack.getItem() instanceof ItemSword && itemstack1.getItem() instanceof ItemSword) {
ItemSword itemsword = (ItemSword) itemstack.getItem();
ItemSword itemsword1 = (ItemSword) itemstack1.getItem();
if (itemsword.g() == itemsword1.g()) {
flag = itemstack.getData() > itemstack1.getData() || itemstack.hasTag() && !itemstack1.hasTag();
} else {
flag = itemsword.g() > itemsword1.g();
}
} else if (itemstack.getItem() instanceof ItemBow && itemstack1.getItem() instanceof ItemBow) {
flag = itemstack.hasTag() && !itemstack1.hasTag();
} else {
flag = false;
}
} else if (itemstack.getItem() instanceof ItemArmor && !(itemstack1.getItem() instanceof ItemArmor)) {
flag = true;
} else if (itemstack.getItem() instanceof ItemArmor && itemstack1.getItem() instanceof ItemArmor && !EnchantmentManager.d(itemstack1)) {
ItemArmor itemarmor = (ItemArmor) itemstack.getItem();
ItemArmor itemarmor1 = (ItemArmor) itemstack1.getItem();
if (itemarmor.d == itemarmor1.d) {
flag = itemstack.getData() > itemstack1.getData() || itemstack.hasTag() && !itemstack1.hasTag();
} else {
flag = itemarmor.d > itemarmor1.d;
}
} else {
flag = false;
}
}
if (flag && this.c(itemstack)) {
double d0;
switch (enumitemslot.a()) {
case HAND:
d0 = this.dropChanceHand[enumitemslot.b()];
break;
case ARMOR:
d0 = this.dropChanceArmor[enumitemslot.b()];
break;
default:
d0 = 0.0D;
}
if (!itemstack1.isEmpty() && this.random.nextFloat() - 0.1F < d0) {
this.forceDrops = true; // CraftBukkit
this.a(itemstack1, 0.0F);
this.forceDrops = false; // CraftBukkit
}
if (itemstack.getItem() == Items.DIAMOND && entityitem.n() != null) {
EntityHuman entityhuman = this.world.a(entityitem.n());
if (entityhuman != null) {
entityhuman.b(AchievementList.x);
}
}
this.setSlot(enumitemslot, itemstack);
switch (enumitemslot.a()) {
case HAND:
this.dropChanceHand[enumitemslot.b()] = 2.0F;
break;
case ARMOR:
this.dropChanceArmor[enumitemslot.b()] = 2.0F;
}
this.persistent = true;
this.receive(entityitem, itemstack.getCount());
entityitem.die();
}
}
protected boolean c(ItemStack itemstack) {
return true;
}
protected boolean isTypeNotPersistent() {
return true;
}
protected void L() {
if (this.persistent) {
this.ticksFarFromPlayer = 0;
} else {
EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D);
if (entityhuman != null && entityhuman.affectsSpawning) { // Paper - Affects Spawning API
double d0 = entityhuman.locX - this.locX;
double d1 = entityhuman.locY - this.locY;
double d2 = entityhuman.locZ - this.locZ;
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
if (d3 > world.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances
this.die();
}
if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d3 > world.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances
this.die();
} else if (d3 < world.paperConfig.softDespawnDistance) { // Paper - custom despawn distances
this.ticksFarFromPlayer = 0;
}
}
}
}
@Override
protected final void doTick() {
++this.ticksFarFromPlayer;
this.world.methodProfiler.a("checkDespawn");
this.L();
// Spigot Start
if ( this.fromMobSpawner )
{
// Paper start - Allow nerfed mobs to jump and float
if (goalFloat != null) {
if (goalFloat.validConditions()) goalFloat.update();
this.getControllerJump().jumpIfSet();
}
// Paper end
return;
}
// Spigot End
this.world.methodProfiler.a("sensing");
this.bv.a();
this.world.methodProfiler.a("targetSelector");
this.targetSelector.a();
this.world.methodProfiler.a("goalSelector");
this.goalSelector.a();
this.world.methodProfiler.a("navigation");
this.navigation.l();
this.world.methodProfiler.a("mob tick");
this.M();
if (this.isPassenger() && this.bB() instanceof EntityInsentient) {
EntityInsentient entityinsentient = (EntityInsentient) this.bB();
entityinsentient.getNavigation().a(this.getNavigation().k(), 1.5D);
entityinsentient.getControllerMove().a(this.getControllerMove());
}
this.world.methodProfiler.a("controls");
this.world.methodProfiler.a("move");
this.moveController.c();
this.world.methodProfiler.c("look");
this.lookController.a();
this.world.methodProfiler.c("jump");
this.g.b();
}
protected void M() {}
public int N() {
return 40;
}
public int cL() {
return 10;
}
public void a(Entity entity, float f, float f1) {
double d0 = entity.locX - this.locX;
double d1 = entity.locZ - this.locZ;
double d2;
if (entity instanceof EntityLiving) {
EntityLiving entityliving = (EntityLiving) entity;
d2 = entityliving.locY + entityliving.getHeadHeight() - (this.locY + this.getHeadHeight());
} else {
d2 = (entity.getBoundingBox().b + entity.getBoundingBox().e) / 2.0D - (this.locY + this.getHeadHeight());
}
double d3 = MathHelper.sqrt(d0 * d0 + d1 * d1);
float f2 = (float) (MathHelper.c(d1, d0) * 57.2957763671875D) - 90.0F;
float f3 = (float) (-(MathHelper.c(d2, d3) * 57.2957763671875D));
this.pitch = this.b(this.pitch, f3, f1);
this.yaw = this.b(this.yaw, f2, f);
}
private float b(float f, float f1, float f2) {
float f3 = MathHelper.g(f1 - f);
if (f3 > f2) {
f3 = f2;
}
if (f3 < -f2) {
f3 = -f2;
}
return f + f3;
}
public boolean isNotColliding() { return this.cM(); } // OBFHELPER
public boolean cM() {
IBlockData iblockdata = this.world.getType((new BlockPosition(this)).down());
return iblockdata.a(this);
}
public boolean canSpawn() {
return !this.world.containsLiquid(this.getBoundingBox()) && this.world.getCubes(this, this.getBoundingBox()).isEmpty() && this.world.a(this.getBoundingBox(), this);
}
public int cQ() {
return 4;
}
@Override
public int aY() {
if (this.getGoalTarget() == null) {
return 3;
} else {
int i = (int) (this.getHealth() - this.getMaxHealth() * 0.33F);
i -= (3 - this.world.getDifficulty().a()) * 4;
if (i < 0) {
i = 0;
}
return i + 3;
}
}
@Override
public Iterable<ItemStack> aG() {
return this.bw;
}
@Override
public Iterable<ItemStack> getArmorItems() {
return this.bx;
}
@Override
public ItemStack getEquipment(EnumItemSlot enumitemslot) {
switch (enumitemslot.a()) {
case HAND:
return this.bw.get(enumitemslot.b());
case ARMOR:
return this.bx.get(enumitemslot.b());
default:
return ItemStack.a;
}
}
@Override
public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) {
switch (enumitemslot.a()) {
case HAND:
this.bw.set(enumitemslot.b(), itemstack);
break;
case ARMOR:
this.bx.set(enumitemslot.b(), itemstack);
}
}
@Override
protected void dropEquipment(boolean flag, int i) {
EnumItemSlot[] aenumitemslot = EnumItemSlot.values();
int j = aenumitemslot.length;
for (int k = 0; k < j; ++k) {
EnumItemSlot enumitemslot = aenumitemslot[k];
ItemStack itemstack = this.getEquipment(enumitemslot);
double d0;
switch (enumitemslot.a()) {
case HAND:
d0 = this.dropChanceHand[enumitemslot.b()];
break;
case ARMOR:
d0 = this.dropChanceArmor[enumitemslot.b()];
break;
default:
d0 = 0.0D;
}
boolean flag1 = d0 > 1.0D;
if (!itemstack.isEmpty() && !EnchantmentManager.e(itemstack) && (flag || flag1) && this.random.nextFloat() - i * 0.01F < d0) {
if (!flag1 && itemstack.f()) {
itemstack.setData(itemstack.k() - this.random.nextInt(1 + this.random.nextInt(Math.max(itemstack.k() - 3, 1))));
}
this.a(itemstack, 0.0F);
}
}
}
protected void a(DifficultyDamageScaler difficultydamagescaler) {
if (this.random.nextFloat() < 0.15F * difficultydamagescaler.d()) {
int i = this.random.nextInt(2);
float f = this.world.getDifficulty() == EnumDifficulty.HARD ? 0.1F : 0.25F;
if (this.random.nextFloat() < 0.095F) {
++i;
}
if (this.random.nextFloat() < 0.095F) {
++i;
}
if (this.random.nextFloat() < 0.095F) {
++i;
}
boolean flag = true;
EnumItemSlot[] aenumitemslot = EnumItemSlot.values();
int j = aenumitemslot.length;
for (int k = 0; k < j; ++k) {
EnumItemSlot enumitemslot = aenumitemslot[k];
if (enumitemslot.a() == EnumItemSlot.Function.ARMOR) {
ItemStack itemstack = this.getEquipment(enumitemslot);
if (!flag && this.random.nextFloat() < f) {
break;
}
flag = false;
if (itemstack.isEmpty()) {
Item item = a(enumitemslot, i);
if (item != null) {
this.setSlot(enumitemslot, new ItemStack(item));
}
}
}
}
}
}
public static EnumItemSlot d(ItemStack itemstack) {
return itemstack.getItem() != Item.getItemOf(Blocks.PUMPKIN) && itemstack.getItem() != Items.SKULL ? (itemstack.getItem() instanceof ItemArmor ? ((ItemArmor) itemstack.getItem()).c : (itemstack.getItem() == Items.cS ? EnumItemSlot.CHEST : (itemstack.getItem() == Items.SHIELD ? EnumItemSlot.OFFHAND : EnumItemSlot.MAINHAND))) : EnumItemSlot.HEAD;
}
@Nullable
public static Item a(EnumItemSlot enumitemslot, int i) {
switch (enumitemslot) {
case HEAD:
if (i == 0) {
return Items.LEATHER_HELMET;
} else if (i == 1) {
return Items.GOLDEN_HELMET;
} else if (i == 2) {
return Items.CHAINMAIL_HELMET;
} else if (i == 3) {
return Items.IRON_HELMET;
} else if (i == 4) {
return Items.DIAMOND_HELMET;
}
case CHEST:
if (i == 0) {
return Items.LEATHER_CHESTPLATE;
} else if (i == 1) {
return Items.GOLDEN_CHESTPLATE;
} else if (i == 2) {
return Items.CHAINMAIL_CHESTPLATE;
} else if (i == 3) {
return Items.IRON_CHESTPLATE;
} else if (i == 4) {
return Items.DIAMOND_CHESTPLATE;
}
case LEGS:
if (i == 0) {
return Items.LEATHER_LEGGINGS;
} else if (i == 1) {
return Items.GOLDEN_LEGGINGS;
} else if (i == 2) {
return Items.CHAINMAIL_LEGGINGS;
} else if (i == 3) {
return Items.IRON_LEGGINGS;
} else if (i == 4) {
return Items.DIAMOND_LEGGINGS;
}
case FEET:
if (i == 0) {
return Items.LEATHER_BOOTS;
} else if (i == 1) {
return Items.GOLDEN_BOOTS;
} else if (i == 2) {
return Items.CHAINMAIL_BOOTS;
} else if (i == 3) {
return Items.IRON_BOOTS;
} else if (i == 4) {
return Items.DIAMOND_BOOTS;
}
default:
return null;
}
}
protected void b(DifficultyDamageScaler difficultydamagescaler) {
float f = difficultydamagescaler.d();
if (!this.getItemInMainHand().isEmpty() && this.random.nextFloat() < 0.25F * f) {
this.setSlot(EnumItemSlot.MAINHAND, EnchantmentManager.a(this.random, this.getItemInMainHand(), (int) (5.0F + f * this.random.nextInt(18)), false));
}
EnumItemSlot[] aenumitemslot = EnumItemSlot.values();
int i = aenumitemslot.length;
for (int j = 0; j < i; ++j) {
EnumItemSlot enumitemslot = aenumitemslot[j];
if (enumitemslot.a() == EnumItemSlot.Function.ARMOR) {
ItemStack itemstack = this.getEquipment(enumitemslot);
if (!itemstack.isEmpty() && this.random.nextFloat() < 0.5F * f) {
this.setSlot(enumitemslot, EnchantmentManager.a(this.random, itemstack, (int) (5.0F + f * this.random.nextInt(18)), false));
}
}
}
}
@Nullable
public GroupDataEntity prepare(DifficultyDamageScaler difficultydamagescaler, @Nullable GroupDataEntity groupdataentity) {
this.getAttributeInstance(GenericAttributes.FOLLOW_RANGE).b(new AttributeModifier("Random spawn bonus", this.random.nextGaussian() * 0.05D, 1));
if (this.random.nextFloat() < 0.05F) {
this.o(true);
} else {
this.o(false);
}
return groupdataentity;
}
public boolean cR() {
return false;
}
public void cS() {
this.persistent = true;
}
public void a(EnumItemSlot enumitemslot, float f) {
switch (enumitemslot.a()) {
case HAND:
this.dropChanceHand[enumitemslot.b()] = f;
break;
case ARMOR:
this.dropChanceArmor[enumitemslot.b()] = f;
}
}
public boolean cT() {
return this.canPickUpLoot;
}
public void m(boolean flag) {
this.canPickUpLoot = flag;
}
public boolean isPersistent() {
return this.persistent;
}
@Override
public final boolean b(EntityHuman entityhuman, EnumHand enumhand) {
if (this.isLeashed() && this.getLeashHolder() == entityhuman) {
// CraftBukkit start - fire PlayerUnleashEntityEvent
if (CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman).isCancelled()) {
((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutAttachEntity(this, this.getLeashHolder()));
return false;
}
// CraftBukkit end
this.unleash(true, !entityhuman.abilities.canInstantlyBuild);
return true;
} else {
ItemStack itemstack = entityhuman.b(enumhand);
if (itemstack.getItem() == Items.LEAD && this.a(entityhuman)) {
// CraftBukkit start - fire PlayerLeashEntityEvent
if (CraftEventFactory.callPlayerLeashEntityEvent(this, entityhuman, entityhuman).isCancelled()) {
((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutAttachEntity(this, this.getLeashHolder()));
return false;
}
// CraftBukkit end
this.setLeashHolder(entityhuman, true);
itemstack.subtract(1);
return true;
} else {
return this.a(entityhuman, enumhand) ? true : super.b(entityhuman, enumhand);
}
}
}
protected boolean a(EntityHuman entityhuman, EnumHand enumhand) {
return false;
}
protected void cV() {
if (this.bF != null) {
this.da();
}
if (this.bD) {
if (!this.isAlive()) {
this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.PLAYER_UNLEASH)); // CraftBukkit
this.unleash(true, true);
}
if (this.leashHolder == null || this.leashHolder.dead) {
this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.HOLDER_GONE)); // CraftBukkit
this.unleash(true, true);
}
}
}
public void unleash(boolean flag, boolean flag1) {
if (this.bD) {
this.bD = false;
this.leashHolder = null;
if (!this.world.isClientSide && flag1) {
this.forceDrops = true; // CraftBukkit
this.a(Items.LEAD, 1);
this.forceDrops = false; // CraftBukkit
}
if (!this.world.isClientSide && flag && this.world instanceof WorldServer) {
((WorldServer) this.world).getTracker().a(this, (new PacketPlayOutAttachEntity(this, (Entity) null)));
}
}
}
public boolean a(EntityHuman entityhuman) {
return !this.isLeashed() && !(this instanceof IMonster);
}
public boolean isLeashed() {
return this.bD;
}
public Entity getLeashHolder() {
return this.leashHolder;
}
public void setLeashHolder(Entity entity, boolean flag) {
this.bD = true;
this.leashHolder = entity;
if (!this.world.isClientSide && flag && this.world instanceof WorldServer) {
((WorldServer) this.world).getTracker().a(this, (new PacketPlayOutAttachEntity(this, this.leashHolder)));
}
if (this.isPassenger()) {
this.stopRiding();
}
}
@Override
public boolean a(Entity entity, boolean flag) {
boolean flag1 = super.a(entity, flag);
if (flag1 && this.isLeashed()) {
this.unleash(true, true);
}
return flag1;
}
private void da() {
if (this.bD && this.bF != null) {
if (this.bF.b("UUID")) {
UUID uuid = this.bF.a("UUID");
List list = this.world.a(EntityLiving.class, this.getBoundingBox().g(10.0D));
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
EntityLiving entityliving = (EntityLiving) iterator.next();
if (entityliving.getUniqueID().equals(uuid)) {
this.setLeashHolder(entityliving, true);
break;
}
}
} else if (this.bF.hasKeyOfType("X", 99) && this.bF.hasKeyOfType("Y", 99) && this.bF.hasKeyOfType("Z", 99)) {
BlockPosition blockposition = new BlockPosition(this.bF.getInt("X"), this.bF.getInt("Y"), this.bF.getInt("Z"));
EntityLeash entityleash = EntityLeash.b(this.world, blockposition);
if (entityleash == null) {
entityleash = EntityLeash.a(this.world, blockposition);
}
this.setLeashHolder(entityleash, true);
} else {
this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit
this.unleash(false, true);
}
}
this.bF = null;
}
@Override
public boolean c(int i, ItemStack itemstack) {
EnumItemSlot enumitemslot;
if (i == 98) {
enumitemslot = EnumItemSlot.MAINHAND;
} else if (i == 99) {
enumitemslot = EnumItemSlot.OFFHAND;
} else if (i == 100 + EnumItemSlot.HEAD.b()) {
enumitemslot = EnumItemSlot.HEAD;
} else if (i == 100 + EnumItemSlot.CHEST.b()) {
enumitemslot = EnumItemSlot.CHEST;
} else if (i == 100 + EnumItemSlot.LEGS.b()) {
enumitemslot = EnumItemSlot.LEGS;
} else {
if (i != 100 + EnumItemSlot.FEET.b()) {
return false;
}
enumitemslot = EnumItemSlot.FEET;
}
if (!itemstack.isEmpty() && !b(enumitemslot, itemstack) && enumitemslot != EnumItemSlot.HEAD) {
return false;
} else {
this.setSlot(enumitemslot, itemstack);
return true;
}
}
@Override
public boolean bA() {
return this.cR() && super.bA();
}
public static boolean b(EnumItemSlot enumitemslot, ItemStack itemstack) {
EnumItemSlot enumitemslot1 = d(itemstack);
return enumitemslot1 == enumitemslot || enumitemslot1 == EnumItemSlot.MAINHAND && enumitemslot == EnumItemSlot.OFFHAND || enumitemslot1 == EnumItemSlot.OFFHAND && enumitemslot == EnumItemSlot.MAINHAND;
}
@Override
public boolean cu() {
return super.cu() && !this.hasAI();
}
public void setAI(boolean flag) {
byte b0 = this.datawatcher.get(EntityInsentient.a).byteValue();
this.datawatcher.set(EntityInsentient.a, Byte.valueOf(flag ? (byte) (b0 | 1) : (byte) (b0 & -2)));
}
public void o(boolean flag) {
byte b0 = this.datawatcher.get(EntityInsentient.a).byteValue();
this.datawatcher.set(EntityInsentient.a, Byte.valueOf(flag ? (byte) (b0 | 2) : (byte) (b0 & -3)));
}
public boolean hasAI() {
return (this.datawatcher.get(EntityInsentient.a).byteValue() & 1) != 0;
}
public boolean cZ() {
return (this.datawatcher.get(EntityInsentient.a).byteValue() & 2) != 0;
}
@Override
public EnumMainHand getMainHand() {
return this.cZ() ? EnumMainHand.LEFT : EnumMainHand.RIGHT;
}
public static enum EnumEntityPositionType {
ON_GROUND, IN_AIR, IN_WATER;
private EnumEntityPositionType() {}
}
}