--- a/net/minecraft/world/entity/monster/EnderMan.java
+++ b/net/minecraft/world/entity/monster/EnderMan.java
@@ -1,6 +1,7 @@
 package net.minecraft.world.entity.monster;
 
 import java.util.EnumSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
@@ -70,8 +71,9 @@
 import net.minecraft.world.phys.Vec3;
 
 public class EnderMan extends Monster implements NeutralMob {
+
     private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0");
-    private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier(SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", (double)0.15F, AttributeModifier.Operation.ADDITION);
+    private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier(EnderMan.SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.15000000596046448D, AttributeModifier.Operation.ADDITION);
     private static final int DELAY_BETWEEN_CREEPY_STARE_SOUND = 400;
     private static final int MIN_DEAGGRESSION_TIME = 600;
     private static final EntityDataAccessor<Optional<BlockState>> DATA_CARRY_STATE = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BLOCK_STATE);
@@ -101,45 +103,63 @@
         this.goalSelector.addGoal(10, new EnderMan.EndermanLeaveBlockGoal(this));
         this.goalSelector.addGoal(11, new EnderMan.EndermanTakeBlockGoal(this));
         this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt));
-        this.targetSelector.addGoal(2, new HurtByTargetGoal(this));
+        this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0]));
         this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, true, false));
         this.targetSelector.addGoal(4, new ResetUniversalAngerTargetGoal<>(this, false));
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 40.0D).add(Attributes.MOVEMENT_SPEED, (double)0.3F).add(Attributes.ATTACK_DAMAGE, 7.0D).add(Attributes.FOLLOW_RANGE, 64.0D);
+        return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 40.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 7.0D).add(Attributes.FOLLOW_RANGE, 64.0D);
     }
 
     @Override
     public void setTarget(@Nullable LivingEntity target) {
-        super.setTarget(target);
-        AttributeInstance attributeInstance = this.getAttribute(Attributes.MOVEMENT_SPEED);
-        if (target == null) {
+        // CraftBukkit start - fire event
+        this.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true);
+    }
+
+    // Paper start
+    private boolean tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason reason) {
+        return new com.destroystokyo.paper.event.entity.EndermanEscapeEvent((org.bukkit.craftbukkit.v1_19_R2.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent();
+    }
+    // Paper end
+
+    @Override
+    public boolean setTarget(LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) {
+        if (!super.setTarget(entityliving, reason, fireEvent)) {
+            return false;
+        }
+        entityliving = getTarget();
+        // CraftBukkit end
+        AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
+
+        if (entityliving == null) {
             this.targetChangeTime = 0;
-            this.entityData.set(DATA_CREEPY, false);
-            this.entityData.set(DATA_STARED_AT, false);
-            attributeInstance.removeModifier(SPEED_MODIFIER_ATTACKING);
+            this.entityData.set(EnderMan.DATA_CREEPY, false);
+            this.entityData.set(EnderMan.DATA_STARED_AT, false);
+            attributemodifiable.removeModifier(EnderMan.SPEED_MODIFIER_ATTACKING);
         } else {
             this.targetChangeTime = this.tickCount;
-            this.entityData.set(DATA_CREEPY, true);
-            if (!attributeInstance.hasModifier(SPEED_MODIFIER_ATTACKING)) {
-                attributeInstance.addTransientModifier(SPEED_MODIFIER_ATTACKING);
+            this.entityData.set(EnderMan.DATA_CREEPY, true);
+            if (!attributemodifiable.hasModifier(EnderMan.SPEED_MODIFIER_ATTACKING)) {
+                attributemodifiable.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING);
             }
         }
+        return true;
 
     }
 
     @Override
     protected void defineSynchedData() {
         super.defineSynchedData();
-        this.entityData.define(DATA_CARRY_STATE, Optional.empty());
-        this.entityData.define(DATA_CREEPY, false);
-        this.entityData.define(DATA_STARED_AT, false);
+        this.entityData.define(EnderMan.DATA_CARRY_STATE, Optional.empty());
+        this.entityData.define(EnderMan.DATA_CREEPY, false);
+        this.entityData.define(EnderMan.DATA_STARED_AT, false);
     }
 
     @Override
     public void startPersistentAngerTimer() {
-        this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random));
+        this.setRemainingPersistentAngerTime(EnderMan.PERSISTENT_ANGER_TIME.sample(this.random));
     }
 
     @Override
@@ -175,7 +195,7 @@
 
     @Override
     public void onSyncedDataUpdated(EntityDataAccessor<?> data) {
-        if (DATA_CREEPY.equals(data) && this.hasBeenStaredAt() && this.level.isClientSide) {
+        if (EnderMan.DATA_CREEPY.equals(data) && this.hasBeenStaredAt() && this.level.isClientSide) {
             this.playStareSound();
         }
 
@@ -185,9 +205,10 @@
     @Override
     public void addAdditionalSaveData(CompoundTag nbt) {
         super.addAdditionalSaveData(nbt);
-        BlockState blockState = this.getCarriedBlock();
-        if (blockState != null) {
-            nbt.put("carriedBlockState", NbtUtils.writeBlockState(blockState));
+        BlockState iblockdata = this.getCarriedBlock();
+
+        if (iblockdata != null) {
+            nbt.put("carriedBlockState", NbtUtils.writeBlockState(iblockdata));
         }
 
         this.addPersistentAngerSaveData(nbt);
@@ -196,29 +217,41 @@
     @Override
     public void readAdditionalSaveData(CompoundTag nbt) {
         super.readAdditionalSaveData(nbt);
-        BlockState blockState = null;
+        BlockState iblockdata = null;
+
         if (nbt.contains("carriedBlockState", 10)) {
-            blockState = NbtUtils.readBlockState(this.level.holderLookup(Registries.BLOCK), nbt.getCompound("carriedBlockState"));
-            if (blockState.isAir()) {
-                blockState = null;
+            iblockdata = NbtUtils.readBlockState(this.level.holderLookup(Registries.BLOCK), nbt.getCompound("carriedBlockState"));
+            if (iblockdata.isAir()) {
+                iblockdata = null;
             }
         }
 
-        this.setCarriedBlock(blockState);
+        this.setCarriedBlock(iblockdata);
         this.readPersistentAngerSaveData(this.level, nbt);
     }
 
-    boolean isLookingAtMe(Player player) {
-        ItemStack itemStack = player.getInventory().armor.get(3);
-        if (itemStack.is(Blocks.CARVED_PUMPKIN.asItem())) {
+    // Paper start - EndermanAttackPlayerEvent
+    private boolean isLookingAtMe(Player player) {
+        boolean shouldAttack = isLookingAtMe_check(player);
+        com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity());
+        event.setCancelled(!shouldAttack);
+        return event.callEvent();
+    }
+    private boolean isLookingAtMe_check(Player player) {
+        // Paper end
+        ItemStack itemstack = (ItemStack) player.getInventory().armor.get(3);
+
+        if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) {
             return false;
         } else {
-            Vec3 vec3 = player.getViewVector(1.0F).normalize();
-            Vec3 vec32 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ());
-            double d = vec32.length();
-            vec32 = vec32.normalize();
-            double e = vec3.dot(vec32);
-            return e > 1.0D - 0.025D / d ? player.hasLineOfSight(this) : false;
+            Vec3 vec3d = player.getViewVector(1.0F).normalize();
+            Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ());
+            double d0 = vec3d1.length();
+
+            vec3d1 = vec3d1.normalize();
+            double d1 = vec3d.dot(vec3d1);
+
+            return d1 > 1.0D - 0.025D / d0 ? player.hasLineOfSight(this) : false;
         }
     }
 
@@ -230,14 +263,14 @@
     @Override
     public void aiStep() {
         if (this.level.isClientSide) {
-            for(int i = 0; i < 2; ++i) {
+            for (int i = 0; i < 2; ++i) {
                 this.level.addParticle(ParticleTypes.PORTAL, this.getRandomX(0.5D), this.getRandomY() - 0.25D, this.getRandomZ(0.5D), (this.random.nextDouble() - 0.5D) * 2.0D, -this.random.nextDouble(), (this.random.nextDouble() - 0.5D) * 2.0D);
             }
         }
 
         this.jumping = false;
         if (!this.level.isClientSide) {
-            this.updatePersistentAnger((ServerLevel)this.level, true);
+            this.updatePersistentAnger((ServerLevel) this.level, true);
         }
 
         super.aiStep();
@@ -252,8 +285,9 @@
     protected void customServerAiStep() {
         if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) {
             float f = this.getLightLevelDependentMagicValue();
-            if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) {
-                this.setTarget((LivingEntity)null);
+
+            if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper
+                this.setTarget((LivingEntity) null);
                 this.teleport();
             }
         }
@@ -261,49 +295,54 @@
         super.customServerAiStep();
     }
 
-    protected boolean teleport() {
+    public boolean teleport() { // Paper - protected->public
         if (!this.level.isClientSide() && this.isAlive()) {
-            double d = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D;
-            double e = this.getY() + (double)(this.random.nextInt(64) - 32);
-            double f = this.getZ() + (this.random.nextDouble() - 0.5D) * 64.0D;
-            return this.teleport(d, e, f);
+            double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D;
+            double d1 = this.getY() + (double) (this.random.nextInt(64) - 32);
+            double d2 = this.getZ() + (this.random.nextDouble() - 0.5D) * 64.0D;
+
+            return this.teleport(d0, d1, d2);
         } else {
             return false;
         }
     }
 
     boolean teleportTowards(Entity entity) {
-        Vec3 vec3 = new Vec3(this.getX() - entity.getX(), this.getY(0.5D) - entity.getEyeY(), this.getZ() - entity.getZ());
-        vec3 = vec3.normalize();
-        double d = 16.0D;
-        double e = this.getX() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3.x * 16.0D;
-        double f = this.getY() + (double)(this.random.nextInt(16) - 8) - vec3.y * 16.0D;
-        double g = this.getZ() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3.z * 16.0D;
-        return this.teleport(e, f, g);
+        Vec3 vec3d = new Vec3(this.getX() - entity.getX(), this.getY(0.5D) - entity.getEyeY(), this.getZ() - entity.getZ());
+
+        vec3d = vec3d.normalize();
+        double d0 = 16.0D;
+        double d1 = this.getX() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.x * 16.0D;
+        double d2 = this.getY() + (double) (this.random.nextInt(16) - 8) - vec3d.y * 16.0D;
+        double d3 = this.getZ() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.z * 16.0D;
+
+        return this.teleport(d1, d2, d3);
     }
 
     private boolean teleport(double x, double y, double z) {
-        BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(x, y, z);
+        BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, y, z);
 
-        while(mutableBlockPos.getY() > this.level.getMinBuildHeight() && !this.level.getBlockState(mutableBlockPos).getMaterial().blocksMotion()) {
-            mutableBlockPos.move(Direction.DOWN);
+        while (blockposition_mutableblockposition.getY() > this.level.getMinBuildHeight() && !this.level.getBlockState(blockposition_mutableblockposition).getMaterial().blocksMotion()) {
+            blockposition_mutableblockposition.move(Direction.DOWN);
         }
 
-        BlockState blockState = this.level.getBlockState(mutableBlockPos);
-        boolean bl = blockState.getMaterial().blocksMotion();
-        boolean bl2 = blockState.getFluidState().is(FluidTags.WATER);
-        if (bl && !bl2) {
-            Vec3 vec3 = this.position();
-            boolean bl3 = this.randomTeleport(x, y, z, true);
-            if (bl3) {
-                this.level.gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of(this));
+        BlockState iblockdata = this.level.getBlockState(blockposition_mutableblockposition);
+        boolean flag = iblockdata.getMaterial().blocksMotion();
+        boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER);
+
+        if (flag && !flag1) {
+            Vec3 vec3d = this.position();
+            boolean flag2 = this.randomTeleport(x, y, z, true);
+
+            if (flag2) {
+                this.level.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) this));
                 if (!this.isSilent()) {
-                    this.level.playSound((Player)null, this.xo, this.yo, this.zo, SoundEvents.ENDERMAN_TELEPORT, this.getSoundSource(), 1.0F, 1.0F);
+                    this.level.playSound((Player) null, this.xo, this.yo, this.zo, SoundEvents.ENDERMAN_TELEPORT, this.getSoundSource(), 1.0F, 1.0F);
                     this.playSound(SoundEvents.ENDERMAN_TELEPORT, 1.0F, 1.0F);
                 }
             }
 
-            return bl3;
+            return flag2;
         } else {
             return false;
         }
@@ -327,26 +366,32 @@
     @Override
     protected void dropCustomDeathLoot(DamageSource source, int lootingMultiplier, boolean allowDrops) {
         super.dropCustomDeathLoot(source, lootingMultiplier, allowDrops);
-        BlockState blockState = this.getCarriedBlock();
-        if (blockState != null) {
-            ItemStack itemStack = new ItemStack(Items.DIAMOND_AXE);
-            itemStack.enchant(Enchantments.SILK_TOUCH, 1);
-            LootContext.Builder builder = (new LootContext.Builder((ServerLevel)this.level)).withRandom(this.level.getRandom()).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemStack).withOptionalParameter(LootContextParams.THIS_ENTITY, this);
+        BlockState iblockdata = this.getCarriedBlock();
 
-            for(ItemStack itemStack2 : blockState.getDrops(builder)) {
-                this.spawnAtLocation(itemStack2);
+        if (iblockdata != null) {
+            ItemStack itemstack = new ItemStack(Items.DIAMOND_AXE);
+
+            itemstack.enchant(Enchantments.SILK_TOUCH, 1);
+            LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withRandom(this.level.getRandom()).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, this);
+            List<ItemStack> list = iblockdata.getDrops(loottableinfo_builder);
+            Iterator iterator = list.iterator();
+
+            while (iterator.hasNext()) {
+                ItemStack itemstack1 = (ItemStack) iterator.next();
+
+                this.spawnAtLocation(itemstack1);
             }
         }
 
     }
 
     public void setCarriedBlock(@Nullable BlockState state) {
-        this.entityData.set(DATA_CARRY_STATE, Optional.ofNullable(state));
+        this.entityData.set(EnderMan.DATA_CARRY_STATE, Optional.ofNullable(state));
     }
 
     @Nullable
     public BlockState getCarriedBlock() {
-        return this.entityData.get(DATA_CARRY_STATE).orElse((BlockState)null);
+        return (BlockState) ((Optional) this.entityData.get(EnderMan.DATA_CARRY_STATE)).orElse((Object) null);
     }
 
     @Override
@@ -355,56 +400,72 @@
             return false;
         } else if (source instanceof IndirectEntityDamageSource) {
             Entity entity = source.getDirectEntity();
-            boolean bl;
+            boolean flag;
+
             if (entity instanceof ThrownPotion) {
-                bl = this.hurtWithCleanWater(source, (ThrownPotion)entity, amount);
+                flag = this.hurtWithCleanWater(source, (ThrownPotion) entity, amount);
             } else {
-                bl = false;
+                flag = false;
             }
 
-            for(int i = 0; i < 64; ++i) {
+            if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start
+            for (int i = 0; i < 64; ++i) {
                 if (this.teleport()) {
                     return true;
                 }
             }
+            } // Paper end
 
-            return bl;
+            return flag;
         } else {
-            boolean bl3 = super.hurt(source, amount);
-            if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) {
+            boolean flag1 = super.hurt(source, amount);
+
+            if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0 && this.tryEscape(source == DamageSource.DROWN ? com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.DROWN : com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684
                 this.teleport();
             }
 
-            return bl3;
+            return flag1;
         }
     }
 
     private boolean hurtWithCleanWater(DamageSource source, ThrownPotion potion, float amount) {
-        ItemStack itemStack = potion.getItem();
-        Potion potion2 = PotionUtils.getPotion(itemStack);
-        List<MobEffectInstance> list = PotionUtils.getMobEffects(itemStack);
-        boolean bl = potion2 == Potions.WATER && list.isEmpty();
-        return bl ? super.hurt(source, amount) : false;
+        ItemStack itemstack = potion.getItem();
+        Potion potionregistry = PotionUtils.getPotion(itemstack);
+        List<MobEffectInstance> list = PotionUtils.getMobEffects(itemstack);
+        boolean flag = potionregistry == Potions.WATER && list.isEmpty();
+
+        return flag ? super.hurt(source, amount) : false;
     }
 
     public boolean isCreepy() {
-        return this.entityData.get(DATA_CREEPY);
+        return (Boolean) this.entityData.get(EnderMan.DATA_CREEPY);
     }
 
     public boolean hasBeenStaredAt() {
-        return this.entityData.get(DATA_STARED_AT);
+        return (Boolean) this.entityData.get(EnderMan.DATA_STARED_AT);
     }
 
     public void setBeingStaredAt() {
-        this.entityData.set(DATA_STARED_AT, true);
+        this.entityData.set(EnderMan.DATA_STARED_AT, true);
+    }
+
+    // Paper start
+    public void setCreepy(boolean creepy) {
+        this.entityData.set(EnderMan.DATA_CREEPY, creepy);
+    }
+
+    public void setHasBeenStaredAt(boolean hasBeenStaredAt) {
+        this.entityData.set(EnderMan.DATA_STARED_AT, hasBeenStaredAt);
     }
+    // Paper end
 
     @Override
     public boolean requiresCustomPersistence() {
         return super.requiresCustomPersistence() || this.getCarriedBlock() != null;
     }
 
-    static class EndermanFreezeWhenLookedAt extends Goal {
+    private static class EndermanFreezeWhenLookedAt extends Goal {
+
         private final EnderMan enderman;
         @Nullable
         private LivingEntity target;
@@ -420,8 +481,9 @@
             if (!(this.target instanceof Player)) {
                 return false;
             } else {
-                double d = this.target.distanceToSqr(this.enderman);
-                return d > 256.0D ? false : this.enderman.isLookingAtMe((Player)this.target);
+                double d0 = this.target.distanceToSqr((Entity) this.enderman);
+
+                return d0 > 256.0D ? false : this.enderman.isLookingAtMe((Player) this.target);
             }
         }
 
@@ -436,7 +498,8 @@
         }
     }
 
-    static class EndermanLeaveBlockGoal extends Goal {
+    private static class EndermanLeaveBlockGoal extends Goal {
+
         private final EnderMan enderman;
 
         public EndermanLeaveBlockGoal(EnderMan enderman) {
@@ -445,33 +508,33 @@
 
         @Override
         public boolean canUse() {
-            if (this.enderman.getCarriedBlock() == null) {
-                return false;
-            } else if (!this.enderman.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
-                return false;
-            } else {
-                return this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0;
-            }
+            return this.enderman.getCarriedBlock() == null ? false : (!this.enderman.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0);
         }
 
         @Override
         public void tick() {
-            RandomSource randomSource = this.enderman.getRandom();
-            Level level = this.enderman.level;
-            int i = Mth.floor(this.enderman.getX() - 1.0D + randomSource.nextDouble() * 2.0D);
-            int j = Mth.floor(this.enderman.getY() + randomSource.nextDouble() * 2.0D);
-            int k = Mth.floor(this.enderman.getZ() - 1.0D + randomSource.nextDouble() * 2.0D);
-            BlockPos blockPos = new BlockPos(i, j, k);
-            BlockState blockState = level.getBlockState(blockPos);
-            BlockPos blockPos2 = blockPos.below();
-            BlockState blockState2 = level.getBlockState(blockPos2);
-            BlockState blockState3 = this.enderman.getCarriedBlock();
-            if (blockState3 != null) {
-                blockState3 = Block.updateFromNeighbourShapes(blockState3, this.enderman.level, blockPos);
-                if (this.canPlaceBlock(level, blockPos, blockState3, blockState, blockState2, blockPos2)) {
-                    level.setBlock(blockPos, blockState3, 3);
-                    level.gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this.enderman, blockState3));
-                    this.enderman.setCarriedBlock((BlockState)null);
+            RandomSource randomsource = this.enderman.getRandom();
+            Level world = this.enderman.level;
+            int i = Mth.floor(this.enderman.getX() - 1.0D + randomsource.nextDouble() * 2.0D);
+            int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 2.0D);
+            int k = Mth.floor(this.enderman.getZ() - 1.0D + randomsource.nextDouble() * 2.0D);
+            BlockPos blockposition = new BlockPos(i, j, k);
+            BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper
+            if (iblockdata == null) return; // Paper
+            BlockPos blockposition1 = blockposition.below();
+            BlockState iblockdata1 = world.getBlockState(blockposition1);
+            BlockState iblockdata2 = this.enderman.getCarriedBlock();
+
+            if (iblockdata2 != null) {
+                iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level, blockposition);
+                if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) {
+                    // CraftBukkit start - Place event
+                    if (!org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2).isCancelled()) {
+                    world.setBlock(blockposition, iblockdata2, 3);
+                    world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2));
+                    this.enderman.setCarriedBlock((BlockState) null);
+                    }
+                    // CraftBukkit end
                 }
 
             }
@@ -482,7 +545,49 @@
         }
     }
 
-    static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal<Player> {
+    private static class EndermanTakeBlockGoal extends Goal {
+
+        private final EnderMan enderman;
+
+        public EndermanTakeBlockGoal(EnderMan enderman) {
+            this.enderman = enderman;
+        }
+
+        @Override
+        public boolean canUse() {
+            return this.enderman.getCarriedBlock() != null ? false : (!this.enderman.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0);
+        }
+
+        @Override
+        public void tick() {
+            RandomSource randomsource = this.enderman.getRandom();
+            Level world = this.enderman.level;
+            int i = Mth.floor(this.enderman.getX() - 2.0D + randomsource.nextDouble() * 4.0D);
+            int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 3.0D);
+            int k = Mth.floor(this.enderman.getZ() - 2.0D + randomsource.nextDouble() * 4.0D);
+            BlockPos blockposition = new BlockPos(i, j, k);
+            BlockState iblockdata = world.getBlockStateIfLoaded(blockposition); // Paper
+            if (iblockdata == null) return; // Paper
+            Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D);
+            Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D);
+            BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman));
+            boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition);
+
+            if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) {
+                // CraftBukkit start - Pickup event
+                if (!org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) {
+                    world.removeBlock(blockposition, false);
+                    world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata));
+                    this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState());
+                }
+                // CraftBukkit end
+            }
+
+        }
+    }
+
+    private static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal<Player> {
+
         private final EnderMan enderman;
         @Nullable
         private Player pendingTarget;
@@ -495,8 +600,8 @@
         public EndermanLookForPlayerGoal(EnderMan enderman, @Nullable Predicate<LivingEntity> targetPredicate) {
             super(enderman, Player.class, 10, false, false, targetPredicate);
             this.enderman = enderman;
-            this.isAngerInducing = (playerEntity) -> {
-                return enderman.isLookingAtMe((Player)playerEntity) || enderman.isAngryAt(playerEntity);
+            this.isAngerInducing = (entityliving) -> {
+                return enderman.isLookingAtMe((Player) entityliving) || enderman.isAngryAt(entityliving);
             };
             this.startAggroTargetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(this.isAngerInducing);
         }
@@ -537,7 +642,7 @@
         @Override
         public void tick() {
             if (this.enderman.getTarget() == null) {
-                super.setTarget((LivingEntity)null);
+                super.setTarget((LivingEntity) null);
             }
 
             if (this.pendingTarget != null) {
@@ -548,13 +653,13 @@
                 }
             } else {
                 if (this.target != null && !this.enderman.isPassenger()) {
-                    if (this.enderman.isLookingAtMe((Player)this.target)) {
-                        if (this.target.distanceToSqr(this.enderman) < 16.0D) {
+                    if (this.enderman.isLookingAtMe((Player) this.target)) {
+                        if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.enderman.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.STARE)) { // Paper
                             this.enderman.teleport();
                         }
 
                         this.teleportTime = 0;
-                    } else if (this.target.distanceToSqr(this.enderman) > 256.0D && this.teleportTime++ >= this.adjustedTickDelay(30) && this.enderman.teleportTowards(this.target)) {
+                    } else if (this.target.distanceToSqr((Entity) this.enderman) > 256.0D && this.teleportTime++ >= this.adjustedTickDelay(30) && this.enderman.teleportTowards(this.target)) {
                         this.teleportTime = 0;
                     }
                 }
@@ -563,45 +668,5 @@
             }
 
         }
-    }
-
-    static class EndermanTakeBlockGoal extends Goal {
-        private final EnderMan enderman;
-
-        public EndermanTakeBlockGoal(EnderMan enderman) {
-            this.enderman = enderman;
-        }
-
-        @Override
-        public boolean canUse() {
-            if (this.enderman.getCarriedBlock() != null) {
-                return false;
-            } else if (!this.enderman.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
-                return false;
-            } else {
-                return this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0;
-            }
-        }
-
-        @Override
-        public void tick() {
-            RandomSource randomSource = this.enderman.getRandom();
-            Level level = this.enderman.level;
-            int i = Mth.floor(this.enderman.getX() - 2.0D + randomSource.nextDouble() * 4.0D);
-            int j = Mth.floor(this.enderman.getY() + randomSource.nextDouble() * 3.0D);
-            int k = Mth.floor(this.enderman.getZ() - 2.0D + randomSource.nextDouble() * 4.0D);
-            BlockPos blockPos = new BlockPos(i, j, k);
-            BlockState blockState = level.getBlockState(blockPos);
-            Vec3 vec3 = new Vec3((double)this.enderman.getBlockX() + 0.5D, (double)j + 0.5D, (double)this.enderman.getBlockZ() + 0.5D);
-            Vec3 vec32 = new Vec3((double)i + 0.5D, (double)j + 0.5D, (double)k + 0.5D);
-            BlockHitResult blockHitResult = level.clip(new ClipContext(vec3, vec32, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman));
-            boolean bl = blockHitResult.getBlockPos().equals(blockPos);
-            if (blockState.is(BlockTags.ENDERMAN_HOLDABLE) && bl) {
-                level.removeBlock(blockPos, false);
-                level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos, GameEvent.Context.of(this.enderman, blockState));
-                this.enderman.setCarriedBlock(blockState.getBlock().defaultBlockState());
-            }
-
-        }
     }
 }
