--- a/net/minecraft/server/EntityInsentient.java +++ b/net/minecraft/server/EntityInsentient.java @@ -10,6 +10,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.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityCombustByEntityEvent; +import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.event.entity.EntityTransformEvent; +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); @@ -28,7 +40,7 @@ public final float[] dropChanceHand; private final NonNullList bx; public final float[] dropChanceArmor; - private boolean canPickUpLoot; + // private boolean canPickUpLoot; // CraftBukkit - moved up to EntityLiving public boolean persistent; private final Map bA; public MinecraftKey lootTableKey; @@ -41,6 +53,8 @@ private BlockPosition bG; private float bH; + public boolean aware = true; // CraftBukkit + protected EntityInsentient(EntityTypes entitytypes, World world) { super(entitytypes, world); this.bw = NonNullList.a(2, ItemStack.b); @@ -64,6 +78,9 @@ this.initPathfinder(); } + // CraftBukkit start - default persistance to type's persistance value + this.persistent = !isTypeNotPersistent(0); + // CraftBukkit end } protected void initPathfinder() {} @@ -144,7 +161,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 @@ -361,16 +409,26 @@ nbttagcompound.setBoolean("NoAI", this.isNoAI()); } + nbttagcompound.setBoolean("Bukkit.Aware", this.aware); // CraftBukkit } @Override public void loadData(NBTTagCompound nbttagcompound) { super.loadData(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; @@ -417,6 +475,11 @@ } this.setNoAI(nbttagcompound.getBoolean("NoAI")); + // CraftBukkit start + if (nbttagcompound.hasKey("Bukkit.Aware")) { + this.aware = nbttagcompound.getBoolean("Bukkit.Aware"); + } + // CraftBukkit end } @Override @@ -424,6 +487,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) { @@ -480,7 +548,7 @@ protected void b(EntityItem entityitem) { ItemStack itemstack = entityitem.getItemStack(); - if (this.g(itemstack)) { + if (this.g(itemstack, entityitem)) { // CraftBukkit - add item this.a(entityitem); this.receive(entityitem, itemstack.getCount()); entityitem.die(); @@ -489,15 +557,29 @@ } public boolean g(ItemStack itemstack) { + // CraftBukkit start - add item + return this.g(itemstack, null); + } + + public boolean g(ItemStack itemstack, EntityItem entityitem) { + // CraftBukkit end EnumItemSlot enumitemslot = j(itemstack); ItemStack itemstack1 = this.getEquipment(enumitemslot); boolean flag = this.a(itemstack, itemstack1); - if (flag && this.canPickup(itemstack)) { + // CraftBukkit start + boolean canPickup = flag && this.canPickup(itemstack); + if (entityitem != null) { + canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); + } + if (canPickup) { + // CraftBukkit end double d0 = (double) this.e(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.b(enumitemslot, itemstack); @@ -610,18 +692,18 @@ EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D); if (entityhuman != null) { - double d0 = entityhuman.h(this); + double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error int i = this.getEntityType().e().f(); int j = i * i; - if (d0 > (double) j && this.isTypeNotPersistent(d0)) { + if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check this.die(); } int k = this.getEntityType().e().g(); int l = k * k; - if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.isTypeNotPersistent(d0)) { + if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check this.die(); } else if (d0 < (double) l) { this.ticksFarFromPlayer = 0; @@ -636,6 +718,7 @@ @Override protected final void doTick() { ++this.ticksFarFromPlayer; + if (!this.aware) return; // CraftBukkit this.world.getMethodProfiler().enter("sensing"); this.bv.a(); this.world.getMethodProfiler().exit(); @@ -1014,6 +1097,12 @@ if (!this.isAlive()) { return EnumInteractionResult.PASS; } 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 EnumInteractionResult.PASS; + } + // CraftBukkit end this.unleash(true, !entityhuman.abilities.canInstantlyBuild); return EnumInteractionResult.a(this.world.isClientSide); } else { @@ -1032,6 +1121,12 @@ 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 EnumInteractionResult.PASS; + } + // CraftBukkit end this.setLeashHolder(entityhuman, true); itemstack.subtract(1); return EnumInteractionResult.a(this.world.isClientSide); @@ -1047,7 +1142,7 @@ if (itemstack.getItem() instanceof ItemMonsterEgg) { if (!this.world.isClientSide) { ItemMonsterEgg itemmonsteregg = (ItemMonsterEgg) itemstack.getItem(); - Optional optional = itemmonsteregg.a(entityhuman, this, this.getEntityType(), this.world, this.getPositionVector(), itemstack); + Optional optional = itemmonsteregg.a(entityhuman, this, (EntityTypes) this.getEntityType(), this.world, this.getPositionVector(), itemstack); // CraftBukkit - decompile error optional.ifPresent((entityinsentient) -> { this.a(entityhuman, entityinsentient); @@ -1098,7 +1193,7 @@ if (this.dead) { return null; } else { - T t0 = (EntityInsentient) entitytypes.a(this.world); + T t0 = entitytypes.a(this.world); // CraftBukkit - decompile error t0.u(this); t0.setCanPickupLoot(this.canPickupLoot()); @@ -1128,7 +1223,12 @@ } } - this.world.addEntity(t0); + // CraftBukkit start + if (CraftEventFactory.callEntityTransformEvent(this, t0, EntityTransformEvent.TransformReason.DROWNED).isCancelled()) { + return null; + } + this.world.addEntity(t0, CreatureSpawnEvent.SpawnReason.DROWNED); + // CraftBukkit end this.die(); return t0; } @@ -1141,6 +1241,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); } @@ -1157,7 +1258,9 @@ this.leashHolder = null; this.bF = 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) { @@ -1207,6 +1310,7 @@ boolean flag1 = super.a(entity, flag); if (flag1 && this.isLeashed()) { + this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit this.unleash(true, true); } @@ -1339,7 +1443,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); @@ -1401,6 +1512,7 @@ @Override protected void bJ() { super.bJ(); + this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit this.unleash(true, false); } }