--- a/net/minecraft/server/EntityInsentient.java +++ b/net/minecraft/server/EntityInsentient.java @@ -9,6 +9,18 @@ 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.entity.LivingEntity; +import org.bukkit.event.entity.EntityCombustByEntityEvent; +import org.bukkit.event.entity.EntityPickupItemEvent; +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 b = DataWatcher.a(EntityInsentient.class, DataWatcherRegistry.a); @@ -27,7 +39,7 @@ public final float[] dropChanceHand; private final NonNullList by; public final float[] dropChanceArmor; - private boolean canPickUpLoot; + // private boolean canPickUpLoot; // CraftBukkit - moved up to EntityLiving public boolean persistent; private final Map bB; public MinecraftKey lootTableKey; @@ -40,6 +52,8 @@ private BlockPosition bH; private float bI; + public boolean aware = true; // CraftBukkit + protected EntityInsentient(EntityTypes entitytypes, World world) { super(entitytypes, world); this.bx = NonNullList.a(2, ItemStack.a); @@ -63,6 +77,9 @@ this.initPathfinder(); } + // CraftBukkit start - default persistance to type's persistance value + this.persistent = !isTypeNotPersistent(0); + // CraftBukkit end } protected void initPathfinder() {} @@ -130,7 +147,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 } @Override @@ -343,16 +391,26 @@ nbttagcompound.setBoolean("NoAI", this.isNoAI()); } + nbttagcompound.setBoolean("Bukkit.Aware", this.aware); // CraftBukkit } @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)) { - this.setCanPickupLoot(nbttagcompound.getBoolean("CanPickUpLoot")); + boolean data = nbttagcompound.getBoolean("CanPickUpLoot"); + if (isLevelAtLeast(nbttagcompound, 1) || data) { + this.setCanPickupLoot(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; @@ -399,6 +457,11 @@ } this.setNoAI(nbttagcompound.getBoolean("NoAI")); + // CraftBukkit start + if (nbttagcompound.hasKey("Bukkit.Aware")) { + this.aware = nbttagcompound.getBoolean("Bukkit.Aware"); + } + // CraftBukkit end } @Override @@ -406,6 +469,11 @@ super.a(damagesource, flag); this.lootTableKey = null; } + // CraftBukkit - start + public MinecraftKey getLootTable() { + return getDefaultLootTable(); + } + // CraftBukkit - end @Override protected LootTableInfo.Builder a(boolean flag, DamageSource damagesource) { @@ -465,11 +533,17 @@ ItemStack itemstack1 = this.getEquipment(enumitemslot); boolean flag = this.a(itemstack, itemstack1, enumitemslot); - if (flag && this.g(itemstack)) { + // CraftBukkit start + boolean canPickup = flag && this.g(itemstack); + canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); + if (canPickup) { + // CraftBukkit end double d0 = (double) this.d(enumitemslot); if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { + this.forceDrops = true; // CraftBukkit this.a(itemstack1); + this.forceDrops = false; // CraftBukkit } this.setSlot(enumitemslot, itemstack); @@ -554,11 +628,11 @@ if (entityhuman != null) { double d0 = entityhuman.h(this); - if (d0 > 16384.0D && this.isTypeNotPersistent(d0)) { + if (d0 > 16384.0D) { // CraftBukkit - remove isTypeNotPersistent() check this.die(); } - if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > 1024.0D && this.isTypeNotPersistent(d0)) { + if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > 1024.0D) { // CraftBukkit - remove isTypeNotPersistent() check this.die(); } else if (d0 < 1024.0D) { this.ticksFarFromPlayer = 0; @@ -573,6 +647,7 @@ @Override protected final void doTick() { ++this.ticksFarFromPlayer; + if (!this.aware) return; // CraftBukkit this.world.getMethodProfiler().enter("sensing"); this.bw.a(); this.world.getMethodProfiler().exit(); @@ -951,12 +1026,24 @@ if (!this.isAlive()) { return false; } else if (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; @@ -1002,6 +1089,7 @@ if (this.leashHolder != null) { if (!this.isAlive() || !this.leashHolder.isAlive()) { + this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit this.unleash(true, true); } @@ -1017,7 +1105,9 @@ this.leashHolder = null; if (!this.world.isClientSide && flag1) { + this.forceDrops = true; // CraftBukkit this.a((IMaterial) Items.LEAD); + this.forceDrops = false; // CraftBukkit } if (!this.world.isClientSide && flag && this.world instanceof WorldServer) { @@ -1086,6 +1176,7 @@ this.setLeashHolder(EntityLeash.a(this.world, blockposition), true); } else { + this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit this.unleash(false, true); } @@ -1193,7 +1284,14 @@ int i = EnchantmentManager.getFireAspectEnchantmentLevel(this); if (i > 0) { - entity.setOnFire(i * 4); + // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item + EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), i * 4); + org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); + + if (!combustEvent.isCancelled()) { + entity.setOnFire(combustEvent.getDuration(), false); + } + // CraftBukkit end } boolean flag = entity.damageEntity(DamageSource.mobAttack(this), f);