--- a/net/minecraft/world/entity/EntityInsentient.java +++ b/net/minecraft/world/entity/EntityInsentient.java @@ -89,6 +89,20 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; import net.minecraft.world.phys.AxisAlignedBB; +// CraftBukkit start +import net.minecraft.server.level.EntityPlayer; +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.EntityRemoveEvent; +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 implements EquipmentUser, Targeting { private static final DataWatcherObject DATA_MOB_FLAGS_ID = DataWatcher.defineId(EntityInsentient.class, DataWatcherRegistry.BYTE); @@ -138,6 +152,8 @@ private BlockPosition restrictCenter; private float restrictRadius; + public boolean aware = true; // CraftBukkit + protected EntityInsentient(EntityTypes entitytypes, World world) { super(entitytypes, world); this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); @@ -165,6 +181,12 @@ } + // CraftBukkit start + public void setPersistenceRequired(boolean persistenceRequired) { + this.persistenceRequired = persistenceRequired; + } + // CraftBukkit end + protected void registerGoals() {} public static AttributeProvider.Builder createMobAttributes() { @@ -269,11 +291,42 @@ @Nullable protected final EntityLiving getTargetFromBrain() { - return (EntityLiving) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null); + return (EntityLiving) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error } public void setTarget(@Nullable EntityLiving entityliving) { + // CraftBukkit start - fire event + setTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true); + } + + public boolean setTarget(EntityLiving entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { + if (getTarget() == entityliving) return false; + if (fireEvent) { + if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getTarget() != null && entityliving == null) { + reason = getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; + } + if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { + this.level().getCraftServer().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); + this.level().getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + + if (event.getTarget() != null) { + entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); + } else { + entityliving = null; + } + } this.target = entityliving; + return true; + // CraftBukkit end } @Override @@ -412,6 +465,12 @@ return null; } + // CraftBukkit start - Add delegate method + public SoundEffect getAmbientSound0() { + return getAmbientSound(); + } + // CraftBukkit end + @Override public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { super.addAdditionalSaveData(nbttagcompound); @@ -486,7 +545,7 @@ } } - if (either != null) { + if (either != null && !this.leashHolder.pluginRemoved) { // CraftBukkit - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin nbttagcompound.put("leash", (NBTBase) either.map((uuid) -> { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); @@ -507,16 +566,26 @@ nbttagcompound.putBoolean("NoAI", this.isNoAi()); } + nbttagcompound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit } @Override public void readAdditionalSaveData(NBTTagCompound nbttagcompound) { super.readAdditionalSaveData(nbttagcompound); + + // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it if (nbttagcompound.contains("CanPickUpLoot", 1)) { - this.setCanPickUpLoot(nbttagcompound.getBoolean("CanPickUpLoot")); + boolean data = nbttagcompound.getBoolean("CanPickUpLoot"); + if (isLevelAtLeast(nbttagcompound, 1) || data) { + this.setCanPickUpLoot(data); + } } - this.persistenceRequired = nbttagcompound.getBoolean("PersistenceRequired"); + boolean data = nbttagcompound.getBoolean("PersistenceRequired"); + if (isLevelAtLeast(nbttagcompound, 1) || data) { + this.persistenceRequired = data; + } + // CraftBukkit end NBTTagList nbttaglist; NBTTagCompound nbttagcompound1; int i; @@ -565,7 +634,7 @@ if (nbttagcompound.contains("leash", 10)) { this.delayedLeashInfo = Either.left(nbttagcompound.getCompound("leash").getUUID("UUID")); } else if (nbttagcompound.contains("leash", 11)) { - this.delayedLeashInfo = (Either) GameProfileSerializer.readBlockPos(nbttagcompound, "leash").map(Either::right).orElse((Object) null); + this.delayedLeashInfo = (Either) GameProfileSerializer.readBlockPos(nbttagcompound, "leash").map(Either::right).orElse(null); // CraftBukkit - decompile error } else { this.delayedLeashInfo = null; } @@ -577,6 +646,11 @@ } this.setNoAi(nbttagcompound.getBoolean("NoAI")); + // CraftBukkit start + if (nbttagcompound.contains("Bukkit.Aware")) { + this.aware = nbttagcompound.getBoolean("Bukkit.Aware"); + } + // CraftBukkit end } @Override @@ -651,20 +725,26 @@ protected void pickUpItem(EntityItem entityitem) { ItemStack itemstack = entityitem.getItem(); - ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy()); + ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), entityitem); // CraftBukkit - add item if (!itemstack1.isEmpty()) { this.onItemPickup(entityitem); this.take(entityitem, itemstack1.getCount()); itemstack.shrink(itemstack1.getCount()); if (itemstack.isEmpty()) { - entityitem.discard(); + entityitem.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause } } } public ItemStack equipItemIfPossible(ItemStack itemstack) { + // CraftBukkit start - add item + return this.equipItemIfPossible(itemstack, null); + } + + public ItemStack equipItemIfPossible(ItemStack itemstack, EntityItem entityitem) { + // CraftBukkit end EnumItemSlot enumitemslot = getEquipmentSlotForItem(itemstack); ItemStack itemstack1 = this.getItemBySlot(enumitemslot); boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1); @@ -675,11 +755,19 @@ flag = itemstack1.isEmpty(); } - if (flag && this.canHoldItem(itemstack)) { + // CraftBukkit start + boolean canPickup = flag && this.canHoldItem(itemstack); + if (entityitem != null) { + canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); + } + if (canPickup) { + // CraftBukkit end double d0 = (double) this.getEquipmentDropChance(enumitemslot); if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { + this.forceDrops = true; // CraftBukkit this.spawnAtLocation(itemstack1); + this.forceDrops = false; // CraftBukkit } if (enumitemslot.isArmor() && itemstack.getCount() > 1) { @@ -813,7 +901,7 @@ @Override public void checkDespawn() { if (this.level().getDifficulty() == EnumDifficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { - this.discard(); + this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { EntityHuman entityhuman = this.level().getNearestPlayer(this, -1.0D); @@ -823,14 +911,14 @@ int j = i * i; if (d0 > (double) j && this.removeWhenFarAway(d0)) { - this.discard(); + this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } int k = this.getType().getCategory().getNoDespawnDistance(); int l = k * k; if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.removeWhenFarAway(d0)) { - this.discard(); + this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } else if (d0 < (double) l) { this.noActionTime = 0; } @@ -844,6 +932,7 @@ @Override protected final void serverAiStep() { ++this.noActionTime; + if (!this.aware) return; // CraftBukkit GameProfilerFiller gameprofilerfiller = this.level().getProfiler(); gameprofilerfiller.push("sensing"); @@ -1311,6 +1400,12 @@ if (!this.isAlive()) { return EnumInteractionResult.PASS; } else if (this.getLeashHolder() == entityhuman) { + // CraftBukkit start - fire PlayerUnleashEntityEvent + if (CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman, enumhand).isCancelled()) { + ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); + return EnumInteractionResult.PASS; + } + // CraftBukkit end this.dropLeash(true, !entityhuman.hasInfiniteMaterials()); this.gameEvent(GameEvent.ENTITY_INTERACT, entityhuman); return EnumInteractionResult.sidedSuccess(this.level().isClientSide); @@ -1336,6 +1431,12 @@ ItemStack itemstack = entityhuman.getItemInHand(enumhand); if (itemstack.is(Items.LEAD) && this.canBeLeashed(entityhuman)) { + // CraftBukkit start - fire PlayerLeashEntityEvent + if (CraftEventFactory.callPlayerLeashEntityEvent(this, entityhuman, entityhuman, enumhand).isCancelled()) { + ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); + return EnumInteractionResult.PASS; + } + // CraftBukkit end this.setLeashedTo(entityhuman, true); itemstack.shrink(1); return EnumInteractionResult.sidedSuccess(this.level().isClientSide); @@ -1351,7 +1452,7 @@ if (itemstack.getItem() instanceof ItemMonsterEgg) { if (this.level() instanceof WorldServer) { ItemMonsterEgg itemmonsteregg = (ItemMonsterEgg) itemstack.getItem(); - Optional optional = itemmonsteregg.spawnOffspringFromSpawnEgg(entityhuman, this, this.getType(), (WorldServer) this.level(), this.position(), itemstack); + Optional optional = itemmonsteregg.spawnOffspringFromSpawnEgg(entityhuman, this, (EntityTypes) this.getType(), (WorldServer) this.level(), this.position(), itemstack); // CraftBukkit - decompile error optional.ifPresent((entityinsentient) -> { this.onOffspringSpawnedFromEgg(entityhuman, entityinsentient); @@ -1401,12 +1502,19 @@ return this.restrictRadius != -1.0F; } + // CraftBukkit start @Nullable public T convertTo(EntityTypes entitytypes, boolean flag) { + return this.convertTo(entitytypes, flag, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + + @Nullable + public T convertTo(EntityTypes entitytypes, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { + // CraftBukkit end if (this.isRemoved()) { return null; } else { - T t0 = (EntityInsentient) entitytypes.create(this.level()); + T t0 = entitytypes.create(this.level()); // CraftBukkit - decompile error if (t0 == null) { return null; @@ -1440,7 +1548,12 @@ } } - this.level().addFreshEntity(t0); + // CraftBukkit start + if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) { + return null; + } + this.level().addFreshEntity(t0, spawnReason); + // CraftBukkit end if (this.isPassenger()) { Entity entity = this.getVehicle(); @@ -1448,7 +1561,7 @@ t0.startRiding(entity, true); } - this.discard(); + this.discard(EntityRemoveEvent.Cause.TRANSFORMATION); // CraftBukkit - add Bukkit remove cause return t0; } } @@ -1461,7 +1574,8 @@ if (this.leashHolder != null) { if (!this.isAlive() || !this.leashHolder.isAlive()) { - this.dropLeash(true, true); + this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit + this.dropLeash(true, !this.leashHolder.pluginRemoved);// CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin } } @@ -1473,7 +1587,9 @@ this.delayedLeashInfo = null; this.clearRestriction(); if (!this.level().isClientSide && flag1) { + this.forceDrops = true; // CraftBukkit this.spawnAtLocation((IMaterial) Items.LEAD); + this.forceDrops = false; // CraftBukkit } if (!this.level().isClientSide && flag && this.level() instanceof WorldServer) { @@ -1527,6 +1643,7 @@ boolean flag1 = super.startRiding(entity, flag); if (flag1 && this.isLeashed()) { + this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit this.dropLeash(true, true); } @@ -1555,7 +1672,9 @@ } if (this.tickCount > 100) { + this.forceDrops = true; // CraftBukkit this.spawnAtLocation((IMaterial) Items.LEAD); + this.forceDrops = false; // CraftBukkit this.delayedLeashInfo = null; } } @@ -1638,14 +1757,21 @@ int i = EnchantmentManager.getFireAspect(this); if (i > 0) { - entity.igniteForSeconds(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.igniteForSeconds(combustEvent.getDuration(), false); + } + // CraftBukkit end } boolean flag = entity.hurt(this.damageSources().mobAttack(this), f); if (flag) { if (f1 > 0.0F && entity instanceof EntityLiving) { - ((EntityLiving) entity).knockback((double) (f1 * 0.5F), (double) MathHelper.sin(this.getYRot() * 0.017453292F), (double) (-MathHelper.cos(this.getYRot() * 0.017453292F))); + ((EntityLiving) entity).knockback((double) (f1 * 0.5F), (double) MathHelper.sin(this.getYRot() * 0.017453292F), (double) (-MathHelper.cos(this.getYRot())) * 0.017453292F, this, org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); // CraftBukkit this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); } @@ -1695,6 +1821,7 @@ @Override protected void removeAfterChangingDimensions() { super.removeAfterChangingDimensions(); + this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit this.dropLeash(true, false); this.getAllSlots().forEach((itemstack) -> { if (!itemstack.isEmpty()) {