aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch')
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch613
1 files changed, 613 insertions, 0 deletions
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch
new file mode 100644
index 0000000000..637fe4721d
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch
@@ -0,0 +1,613 @@
+--- a/net/minecraft/world/entity/monster/EnderMan.java
++++ b/net/minecraft/world/entity/monster/EnderMan.java
+@@ -30,10 +30,10 @@
+ import net.minecraft.world.effect.MobEffectInstance;
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.entity.EntityDimensions;
++import net.minecraft.world.entity.EntityPose;
+ import net.minecraft.world.entity.EntityType;
+ import net.minecraft.world.entity.LivingEntity;
+ import net.minecraft.world.entity.NeutralMob;
+-import net.minecraft.world.entity.Pose;
+ import net.minecraft.world.entity.ai.attributes.AttributeInstance;
+ import net.minecraft.world.entity.ai.attributes.AttributeModifier;
+ import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
+@@ -61,7 +61,7 @@
+ import net.minecraft.world.level.Level;
+ import net.minecraft.world.level.block.Block;
+ import net.minecraft.world.level.block.Blocks;
+-import net.minecraft.world.level.block.state.BlockState;
++import net.minecraft.world.level.block.state.IBlockData;
+ import net.minecraft.world.level.gameevent.GameEvent;
+ import net.minecraft.world.level.pathfinder.BlockPathTypes;
+ import net.minecraft.world.level.storage.loot.LootParams;
+@@ -71,13 +71,18 @@
+ import net.minecraft.world.phys.Vec3;
+ import org.joml.Vector3f;
+
++// CraftBukkit start;
++import org.bukkit.craftbukkit.event.CraftEventFactory;
++import org.bukkit.event.entity.EntityTargetEvent;
++// CraftBukkit end
++
+ 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(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.OPTIONAL_BLOCK_STATE);
++ private static final EntityDataAccessor<Optional<IBlockData>> DATA_CARRY_STATE = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.OPTIONAL_BLOCK_STATE);
+ private static final EntityDataAccessor<Boolean> DATA_CREEPY = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN);
+ private static final EntityDataAccessor<Boolean> DATA_STARED_AT = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN);
+ private int lastStareSound = Integer.MIN_VALUE;
+@@ -87,14 +92,13 @@
+ @Nullable
+ private UUID persistentAngerTarget;
+
+- public EnderMan(EntityType<? extends EnderMan> entitytype, Level level) {
+- super(entitytype, level);
++ public EnderMan(EntityType<? extends EnderMan> entityType, Level level) {
++ super(entityType, level);
+ this.setMaxUpStep(1.0F);
+ this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F);
+ }
+
+ @Override
+- @Override
+ protected void registerGoals() {
+ this.goalSelector.addGoal(0, new FloatGoal(this));
+ this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this));
+@@ -115,28 +119,37 @@
+ }
+
+ @Override
++ public void setTarget(@Nullable LivingEntity livingEntity) {
++ // CraftBukkit start - fire event
++ setTarget(livingEntity, EntityTargetEvent.TargetReason.UNKNOWN, true);
++ }
++
+ @Override
+- public void setTarget(@Nullable LivingEntity livingentity) {
+- super.setTarget(livingentity);
+- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED);
++ public boolean setTarget(LivingEntity entityliving, 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 (livingentity == null) {
++ if (entityliving == null) {
+ this.targetChangeTime = 0;
+ this.entityData.set(EnderMan.DATA_CREEPY, false);
+ this.entityData.set(EnderMan.DATA_STARED_AT, false);
+- attributeinstance.removeModifier(EnderMan.SPEED_MODIFIER_ATTACKING.getId());
++ attributemodifiable.removeModifier(EnderMan.SPEED_MODIFIER_ATTACKING.getId());
+ } else {
+ this.targetChangeTime = this.tickCount;
+ this.entityData.set(EnderMan.DATA_CREEPY, true);
+- if (!attributeinstance.hasModifier(EnderMan.SPEED_MODIFIER_ATTACKING)) {
+- attributeinstance.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING);
++ if (!attributemodifiable.hasModifier(EnderMan.SPEED_MODIFIER_ATTACKING)) {
++ attributemodifiable.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING);
+ }
+ }
++ return true;
+
+ }
+
+ @Override
+- @Override
+ protected void defineSynchedData() {
+ super.defineSynchedData();
+ this.entityData.define(EnderMan.DATA_CARRY_STATE, Optional.empty());
+@@ -145,32 +158,27 @@
+ }
+
+ @Override
+- @Override
+ public void startPersistentAngerTimer() {
+ this.setRemainingPersistentAngerTime(EnderMan.PERSISTENT_ANGER_TIME.sample(this.random));
+ }
+
+ @Override
+- @Override
+- public void setRemainingPersistentAngerTime(int i) {
+- this.remainingPersistentAngerTime = i;
++ public void setRemainingPersistentAngerTime(int time) {
++ this.remainingPersistentAngerTime = time;
+ }
+
+ @Override
+- @Override
+ public int getRemainingPersistentAngerTime() {
+ return this.remainingPersistentAngerTime;
+ }
+
+ @Override
+- @Override
+- public void setPersistentAngerTarget(@Nullable UUID uuid) {
+- this.persistentAngerTarget = uuid;
++ public void setPersistentAngerTarget(@Nullable UUID target) {
++ this.persistentAngerTarget = target;
+ }
+
+ @Nullable
+ @Override
+- @Override
+ public UUID getPersistentAngerTarget() {
+ return this.persistentAngerTarget;
+ }
+@@ -186,43 +194,40 @@
+ }
+
+ @Override
+- @Override
+- public void onSyncedDataUpdated(EntityDataAccessor<?> entitydataaccessor) {
+- if (EnderMan.DATA_CREEPY.equals(entitydataaccessor) && this.hasBeenStaredAt() && this.level().isClientSide) {
++ public void onSyncedDataUpdated(EntityDataAccessor<?> key) {
++ if (EnderMan.DATA_CREEPY.equals(key) && this.hasBeenStaredAt() && this.level().isClientSide) {
+ this.playStareSound();
+ }
+
+- super.onSyncedDataUpdated(entitydataaccessor);
++ super.onSyncedDataUpdated(key);
+ }
+
+ @Override
+- @Override
+- public void addAdditionalSaveData(CompoundTag compoundtag) {
+- super.addAdditionalSaveData(compoundtag);
+- BlockState blockstate = this.getCarriedBlock();
++ public void addAdditionalSaveData(CompoundTag compound) {
++ super.addAdditionalSaveData(compound);
++ IBlockData iblockdata = this.getCarriedBlock();
+
+- if (blockstate != null) {
+- compoundtag.put("carriedBlockState", NbtUtils.writeBlockState(blockstate));
++ if (iblockdata != null) {
++ compound.put("carriedBlockState", NbtUtils.writeBlockState(iblockdata));
+ }
+
+- this.addPersistentAngerSaveData(compoundtag);
++ this.addPersistentAngerSaveData(compound);
+ }
+
+ @Override
+- @Override
+- public void readAdditionalSaveData(CompoundTag compoundtag) {
+- super.readAdditionalSaveData(compoundtag);
+- BlockState blockstate = null;
++ public void readAdditionalSaveData(CompoundTag compound) {
++ super.readAdditionalSaveData(compound);
++ IBlockData iblockdata = null;
+
+- if (compoundtag.contains("carriedBlockState", 10)) {
+- blockstate = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compoundtag.getCompound("carriedBlockState"));
+- if (blockstate.isAir()) {
+- blockstate = null;
++ if (compound.contains("carriedBlockState", 10)) {
++ iblockdata = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("carriedBlockState"));
++ if (iblockdata.isAir()) {
++ iblockdata = null;
+ }
+ }
+
+- this.setCarriedBlock(blockstate);
+- this.readPersistentAngerSaveData(this.level(), compoundtag);
++ this.setCarriedBlock(iblockdata);
++ this.readPersistentAngerSaveData(this.level(), compound);
+ }
+
+ boolean isLookingAtMe(Player player) {
+@@ -231,31 +236,28 @@
+ if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) {
+ return false;
+ } else {
+- Vec3 vec3 = player.getViewVector(1.0F).normalize();
+- Vec3 vec31 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ());
+- double d0 = vec31.length();
++ 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();
+
+- vec31 = vec31.normalize();
+- double d1 = vec3.dot(vec31);
++ vec3d1 = vec3d1.normalize();
++ double d1 = vec3d.dot(vec3d1);
+
+ return d1 > 1.0D - 0.025D / d0 ? player.hasLineOfSight(this) : false;
+ }
+ }
+
+ @Override
+- @Override
+- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) {
++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) {
+ return 2.55F;
+ }
+
+ @Override
+- @Override
+- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) {
+- return new Vector3f(0.0F, entitydimensions.height - 0.09375F * f, 0.0F);
++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) {
++ return new Vector3f(0.0F, entitysize.height - 0.09375F * f, 0.0F);
+ }
+
+ @Override
+- @Override
+ public void aiStep() {
+ if (this.level().isClientSide) {
+ for (int i = 0; i < 2; ++i) {
+@@ -272,13 +274,11 @@
+ }
+
+ @Override
+- @Override
+ public boolean isSensitiveToWater() {
+ return true;
+ }
+
+ @Override
+- @Override
+ protected void customServerAiStep() {
+ if (this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) {
+ float f = this.getLightLevelDependentMagicValue();
+@@ -292,7 +292,7 @@
+ super.customServerAiStep();
+ }
+
+- protected boolean teleport() {
++ public boolean teleport() {
+ if (!this.level().isClientSide() && this.isAlive()) {
+ double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D;
+ double d1 = this.getY() + (double) (this.random.nextInt(64) - 32);
+@@ -304,35 +304,35 @@
+ }
+ }
+
+- boolean teleportTowards(Entity entity) {
+- Vec3 vec3 = new Vec3(this.getX() - entity.getX(), this.getY(0.5D) - entity.getEyeY(), this.getZ() - entity.getZ());
++ public boolean teleportTowards(Entity target) {
++ Vec3 vec3d = new Vec3(this.getX() - target.getX(), this.getY(0.5D) - target.getEyeY(), this.getZ() - target.getZ());
+
+- vec3 = vec3.normalize();
++ vec3d = vec3d.normalize();
+ double d0 = 16.0D;
+- double d1 = this.getX() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3.x * 16.0D;
+- double d2 = this.getY() + (double) (this.random.nextInt(16) - 8) - vec3.y * 16.0D;
+- double d3 = this.getZ() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3.z * 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 d0, double d1, double d2) {
+- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(d0, d1, d2);
++ private boolean teleport(double x, double d1, double y) {
++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, d1, y);
+
+- while (blockpos_mutableblockpos.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockpos_mutableblockpos).blocksMotion()) {
+- blockpos_mutableblockpos.move(Direction.DOWN);
++ while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockposition_mutableblockposition).blocksMotion()) {
++ blockposition_mutableblockposition.move(Direction.DOWN);
+ }
+
+- BlockState blockstate = this.level().getBlockState(blockpos_mutableblockpos);
+- boolean flag = blockstate.blocksMotion();
+- boolean flag1 = blockstate.getFluidState().is(FluidTags.WATER);
++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition);
++ boolean flag = iblockdata.blocksMotion();
++ boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER);
+
+ if (flag && !flag1) {
+- Vec3 vec3 = this.position();
+- boolean flag2 = this.randomTeleport(d0, d1, d2, true);
++ Vec3 vec3d = this.position();
++ boolean flag2 = this.randomTeleport(x, d1, y, true);
+
+ if (flag2) {
+- this.level().gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of((Entity) this));
++ 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.playSound(SoundEvents.ENDERMAN_TELEPORT, 1.0F, 1.0F);
+@@ -346,35 +346,31 @@
+ }
+
+ @Override
+- @Override
+ protected SoundEvent getAmbientSound() {
+ return this.isCreepy() ? SoundEvents.ENDERMAN_SCREAM : SoundEvents.ENDERMAN_AMBIENT;
+ }
+
+ @Override
+- @Override
+- protected SoundEvent getHurtSound(DamageSource damagesource) {
++ protected SoundEvent getHurtSound(DamageSource damageSource) {
+ return SoundEvents.ENDERMAN_HURT;
+ }
+
+ @Override
+- @Override
+ protected SoundEvent getDeathSound() {
+ return SoundEvents.ENDERMAN_DEATH;
+ }
+
+ @Override
+- @Override
+- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) {
+- super.dropCustomDeathLoot(damagesource, i, flag);
+- BlockState blockstate = this.getCarriedBlock();
++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) {
++ super.dropCustomDeathLoot(source, looting, recentlyHit);
++ IBlockData iblockdata = this.getCarriedBlock();
+
+- if (blockstate != null) {
++ if (iblockdata != null) {
+ ItemStack itemstack = new ItemStack(Items.DIAMOND_AXE);
+
+ itemstack.enchant(Enchantments.SILK_TOUCH, 1);
+- LootParams.Builder lootparams_builder = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, this);
+- List<ItemStack> list = blockstate.getDrops(lootparams_builder);
++ LootParams.Builder lootparams_a = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, this);
++ List<ItemStack> list = iblockdata.getDrops(lootparams_a);
+ Iterator iterator = list.iterator();
+
+ while (iterator.hasNext()) {
+@@ -386,33 +382,32 @@
+
+ }
+
+- public void setCarriedBlock(@Nullable BlockState blockstate) {
+- this.entityData.set(EnderMan.DATA_CARRY_STATE, Optional.ofNullable(blockstate));
++ public void setCarriedBlock(@Nullable IBlockData state) {
++ this.entityData.set(EnderMan.DATA_CARRY_STATE, Optional.ofNullable(state));
+ }
+
+ @Nullable
+- public BlockState getCarriedBlock() {
+- return (BlockState) ((Optional) this.entityData.get(EnderMan.DATA_CARRY_STATE)).orElse((Object) null);
++ public IBlockData getCarriedBlock() {
++ return (IBlockData) ((Optional) this.entityData.get(EnderMan.DATA_CARRY_STATE)).orElse((Object) null);
+ }
+
+ @Override
+- @Override
+- public boolean hurt(DamageSource damagesource, float f) {
+- if (this.isInvulnerableTo(damagesource)) {
++ public boolean hurt(DamageSource source, float amount) {
++ if (this.isInvulnerableTo(source)) {
+ return false;
+ } else {
+- boolean flag = damagesource.getDirectEntity() instanceof ThrownPotion;
++ boolean flag = source.getDirectEntity() instanceof ThrownPotion;
+ boolean flag1;
+
+- if (!damagesource.is(DamageTypeTags.IS_PROJECTILE) && !flag) {
+- flag1 = super.hurt(damagesource, f);
+- if (!this.level().isClientSide() && !(damagesource.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) {
++ if (!source.is(DamageTypeTags.IS_PROJECTILE) && !flag) {
++ flag1 = super.hurt(source, amount);
++ if (!this.level().isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) {
+ this.teleport();
+ }
+
+ return flag1;
+ } else {
+- flag1 = flag && this.hurtWithCleanWater(damagesource, (ThrownPotion) damagesource.getDirectEntity(), f);
++ flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion) source.getDirectEntity(), amount);
+
+ for (int i = 0; i < 64; ++i) {
+ if (this.teleport()) {
+@@ -425,13 +420,13 @@
+ }
+ }
+
+- private boolean hurtWithCleanWater(DamageSource damagesource, ThrownPotion thrownpotion, float f) {
+- ItemStack itemstack = thrownpotion.getItem();
+- Potion potion = PotionUtils.getPotion(itemstack);
++ private boolean hurtWithCleanWater(DamageSource source, ThrownPotion potion, float amount) {
++ ItemStack itemstack = potion.getItem();
++ Potion potionregistry = PotionUtils.getPotion(itemstack);
+ List<MobEffectInstance> list = PotionUtils.getMobEffects(itemstack);
+- boolean flag = potion == Potions.WATER && list.isEmpty();
++ boolean flag = potionregistry == Potions.WATER && list.isEmpty();
+
+- return flag ? super.hurt(damagesource, f) : false;
++ return flag ? super.hurt(source, amount) : false;
+ }
+
+ public boolean isCreepy() {
+@@ -447,7 +442,6 @@
+ }
+
+ @Override
+- @Override
+ public boolean requiresCustomPersistence() {
+ return super.requiresCustomPersistence() || this.getCarriedBlock() != null;
+ }
+@@ -460,11 +454,10 @@
+
+ public EndermanFreezeWhenLookedAt(EnderMan enderman) {
+ this.enderman = enderman;
+- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE));
++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE));
+ }
+
+ @Override
+- @Override
+ public boolean canUse() {
+ this.target = this.enderman.getTarget();
+ if (!(this.target instanceof Player)) {
+@@ -477,13 +470,11 @@
+ }
+
+ @Override
+- @Override
+ public void start() {
+ this.enderman.getNavigation().stop();
+ }
+
+ @Override
+- @Override
+ public void tick() {
+ this.enderman.getLookControl().setLookAt(this.target.getX(), this.target.getEyeY(), this.target.getZ());
+ }
+@@ -498,38 +489,38 @@
+ }
+
+ @Override
+- @Override
+ public boolean canUse() {
+ return this.enderman.getCarriedBlock() == null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0);
+ }
+
+ @Override
+- @Override
+ public void tick() {
+ RandomSource randomsource = this.enderman.getRandom();
+- Level level = this.enderman.level();
++ 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 blockpos = new BlockPos(i, j, k);
+- BlockState blockstate = level.getBlockState(blockpos);
+- BlockPos blockpos1 = blockpos.below();
+- BlockState blockstate1 = level.getBlockState(blockpos1);
+- BlockState blockstate2 = this.enderman.getCarriedBlock();
++ BlockPos blockposition = new BlockPos(i, j, k);
++ IBlockData iblockdata = world.getBlockState(blockposition);
++ BlockPos blockposition1 = blockposition.below();
++ IBlockData iblockdata1 = world.getBlockState(blockposition1);
++ IBlockData iblockdata2 = this.enderman.getCarriedBlock();
+
+- if (blockstate2 != null) {
+- blockstate2 = Block.updateFromNeighbourShapes(blockstate2, this.enderman.level(), blockpos);
+- if (this.canPlaceBlock(level, blockpos, blockstate2, blockstate, blockstate1, blockpos1)) {
+- level.setBlock(blockpos, blockstate2, 3);
+- level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(this.enderman, blockstate2));
+- this.enderman.setCarriedBlock((BlockState) null);
++ if (iblockdata2 != null) {
++ iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition);
++ if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) {
++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event
++ world.setBlock(blockposition, iblockdata2, 3);
++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2));
++ this.enderman.setCarriedBlock((IBlockData) null);
++ } // CraftBukkit
+ }
+
+ }
+ }
+
+- private boolean canPlaceBlock(Level level, BlockPos blockpos, BlockState blockstate, BlockState blockstate1, BlockState blockstate2, BlockPos blockpos1) {
+- return blockstate1.isAir() && !blockstate2.isAir() && !blockstate2.is(Blocks.BEDROCK) && blockstate2.isCollisionShapeFullBlock(level, blockpos1) && blockstate.canSurvive(level, blockpos) && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(blockpos))).isEmpty();
++ private boolean canPlaceBlock(Level level, BlockPos destinationPos, IBlockData carriedState, IBlockData destinationState, IBlockData belowDestinationState, BlockPos belowDestinationPos) {
++ return destinationState.isAir() && !belowDestinationState.isAir() && !belowDestinationState.is(Blocks.BEDROCK) && belowDestinationState.isCollisionShapeFullBlock(level, belowDestinationPos) && carriedState.canSurvive(level, destinationPos) && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(destinationPos))).isEmpty();
+ }
+ }
+
+@@ -542,30 +533,30 @@
+ }
+
+ @Override
+- @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
+- @Override
+ public void tick() {
+ RandomSource randomsource = this.enderman.getRandom();
+- Level level = this.enderman.level();
++ 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 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 vec31 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D);
+- BlockHitResult blockhitresult = level.clip(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman));
+- boolean flag = blockhitresult.getBlockPos().equals(blockpos);
++ BlockPos blockposition = new BlockPos(i, j, k);
++ IBlockData iblockdata = world.getBlockState(blockposition);
++ 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 (blockstate.is(BlockTags.ENDERMAN_HOLDABLE) && flag) {
+- level.removeBlock(blockpos, false);
+- level.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(this.enderman, blockstate));
+- this.enderman.setCarriedBlock(blockstate.getBlock().defaultBlockState());
++ if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) {
++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event
++ world.removeBlock(blockposition, false);
++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata));
++ this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState());
++ } // CraftBukkit
+ }
+
+ }
+@@ -582,24 +573,22 @@
+ private final TargetingConditions continueAggroTargetConditions = TargetingConditions.forCombat().ignoreLineOfSight();
+ private final Predicate<LivingEntity> isAngerInducing;
+
+- public EndermanLookForPlayerGoal(EnderMan enderman, @Nullable Predicate<LivingEntity> predicate) {
+- super(enderman, Player.class, 10, false, false, predicate);
++ public EndermanLookForPlayerGoal(EnderMan enderman, @Nullable Predicate<LivingEntity> selectionPredicate) {
++ super(enderman, Player.class, 10, false, false, selectionPredicate);
+ this.enderman = enderman;
+- this.isAngerInducing = (livingentity) -> {
+- return (enderman.isLookingAtMe((Player) livingentity) || enderman.isAngryAt(livingentity)) && !enderman.hasIndirectPassenger(livingentity);
++ this.isAngerInducing = (entityliving) -> {
++ return (enderman.isLookingAtMe((Player) entityliving) || enderman.isAngryAt(entityliving)) && !enderman.hasIndirectPassenger(entityliving);
+ };
+ this.startAggroTargetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(this.isAngerInducing);
+ }
+
+ @Override
+- @Override
+ public boolean canUse() {
+ this.pendingTarget = this.enderman.level().getNearestPlayer(this.startAggroTargetConditions, this.enderman);
+ return this.pendingTarget != null;
+ }
+
+ @Override
+- @Override
+ public void start() {
+ this.aggroTime = this.adjustedTickDelay(5);
+ this.teleportTime = 0;
+@@ -607,14 +596,12 @@
+ }
+
+ @Override
+- @Override
+ public void stop() {
+ this.pendingTarget = null;
+ super.stop();
+ }
+
+ @Override
+- @Override
+ public boolean canContinueToUse() {
+ if (this.pendingTarget != null) {
+ if (!this.isAngerInducing.test(this.pendingTarget)) {
+@@ -639,7 +626,6 @@
+ }
+
+ @Override
+- @Override
+ public void tick() {
+ if (this.enderman.getTarget() == null) {
+ super.setTarget((LivingEntity) null);