--- a/net/minecraft/server/EntityInsentient.java +++ b/net/minecraft/server/EntityInsentient.java @@ -9,6 +9,15 @@ 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); @@ -57,6 +66,9 @@ this.r(); } + // CraftBukkit start - default persistance to type's persistance value + this.persistent = !isTypeNotPersistent(); + // CraftBukkit end } protected void r() {} @@ -110,7 +122,38 @@ } 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) { @@ -340,11 +383,20 @@ 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)) { - this.m(nbttagcompound.getBoolean("CanPickUpLoot")); + boolean data = nbttagcompound.getBoolean("CanPickUpLoot"); + if (isLevelAtLeast(nbttagcompound, 1) || data) { + this.m(data); + } } - this.persistent = nbttagcompound.getBoolean("PersistenceRequired"); + boolean data = nbttagcompound.getBoolean("PersistenceRequired"); + if (isLevelAtLeast(nbttagcompound, 1) || data) { + this.persistent = data; + } + // CraftBukkit end NBTTagList nbttaglist; int i; @@ -525,7 +577,9 @@ } if (!itemstack1.isEmpty() && (double) (this.random.nextFloat() - 0.1F) < d0) { + this.forceDrops = true; // CraftBukkit this.a(itemstack1, 0.0F); + this.forceDrops = false; // CraftBukkit } this.setSlot(enumitemslot, itemstack); @@ -565,11 +619,11 @@ double d2 = entityhuman.locZ - this.locZ; double d3 = d0 * d0 + d1 * d1 + d2 * d2; - if (this.isTypeNotPersistent() && d3 > 16384.0D) { + if (d3 > 16384.0D) { // CraftBukkit - remove isTypeNotPersistent() check this.die(); } - if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d3 > 1024.0D && this.isTypeNotPersistent()) { + if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d3 > 1024.0D) { // CraftBukkit - remove isTypeNotPersistent() check this.die(); } else if (d3 < 1024.0D) { this.ticksFarFromPlayer = 0; @@ -938,12 +992,24 @@ 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; @@ -964,10 +1030,12 @@ if (this.bE) { 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); } } @@ -978,7 +1046,9 @@ this.bE = 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) { @@ -1048,6 +1118,7 @@ this.setLeashHolder(entityleash, true); } else { + this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit this.unleash(false, true); } }