--- a/net/minecraft/world/entity/NeutralMob.java +++ b/net/minecraft/world/entity/NeutralMob.java @@ -8,6 +8,9 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; +// CraftBukkit start +import org.bukkit.event.entity.EntityTargetEvent; +// CraftBukkit end public interface NeutralMob { @@ -42,24 +45,11 @@ UUID uuid = nbt.getUUID("AngryAt"); this.setPersistentAngerTarget(uuid); - Entity entity = ((ServerLevel) world).getEntity(uuid); - - if (entity != null) { - if (entity instanceof Mob) { - Mob entityinsentient = (Mob) entity; - - this.setTarget(entityinsentient); - this.setLastHurtByMob(entityinsentient); - } - - if (entity instanceof Player) { - Player entityhuman = (Player) entity; - - this.setTarget(entityhuman); - this.setLastHurtByPlayer(entityhuman); - } - - } + // Paper - Prevent entity loading causing async lookups; Moved diff to separate method + // If this entity already survived its first tick, e.g. is loaded and ticked in sync, actively + // tick the initial persistent anger. + // If not, let the first tick on the baseTick call the method later down the line. + if (this instanceof Entity entity && !entity.firstTick) this.tickInitialPersistentAnger(world); } } } @@ -114,7 +104,7 @@ default void stopBeingAngry() { this.setLastHurtByMob((LivingEntity) null); this.setPersistentAngerTarget((UUID) null); - this.setTarget((LivingEntity) null); + this.setTarget((LivingEntity) null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit this.setRemainingPersistentAngerTime(0); } @@ -127,8 +117,34 @@ void setTarget(@Nullable LivingEntity target); + boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit + boolean canAttack(LivingEntity target); @Nullable LivingEntity getTarget(); + + // Paper start - Prevent entity loading causing async lookups + // Update last hurt when ticking + default void tickInitialPersistentAnger(Level level) { + UUID target = getPersistentAngerTarget(); + if (target == null) { + return; + } + + Entity entity = ((ServerLevel) level).getEntity(target); + + if (entity != null) { + if (entity instanceof Mob mob) { + this.setTarget(mob, EntityTargetEvent.TargetReason.UNKNOWN, false); // CraftBukkit + this.setLastHurtByMob(mob); + } + + if (entity instanceof Player player) { + this.setTarget(player, EntityTargetEvent.TargetReason.UNKNOWN, false); // CraftBukkit + this.setLastHurtByPlayer(player); + } + } + } + // Paper end - Prevent entity loading causing async lookups }