aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch
diff options
context:
space:
mode:
authorMiniDigger | Martin <[email protected]>2024-01-14 11:04:49 +0100
committerMiniDigger | Martin <[email protected]>2024-01-14 11:04:49 +0100
commitbee74680e607c2e29b038329f62181238911cd83 (patch)
tree708fd1a4a0227d9071243adf2a42d5e9e96cde4a /patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch
parent0a44692ef6ff6e255d48eb3ba1bb114166eafda9 (diff)
downloadPaper-softspoon.tar.gz
Paper-softspoon.zip
add remapped patches as a testsoftspoon
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch')
-rw-r--r--patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch1732
1 files changed, 1732 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch
new file mode 100644
index 0000000000..143349d38a
--- /dev/null
+++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch
@@ -0,0 +1,1732 @@
+--- a/net/minecraft/world/entity/Mob.java
++++ b/net/minecraft/world/entity/Mob.java
+@@ -3,6 +3,8 @@
+ import com.google.common.annotations.VisibleForTesting;
+ import com.google.common.collect.Maps;
+ import java.util.Arrays;
++import java.util.Iterator;
++import java.util.List;
+ import java.util.Map;
+ import java.util.Optional;
+ import java.util.UUID;
+@@ -23,13 +25,14 @@
+ import net.minecraft.network.syncher.SynchedEntityData;
+ import net.minecraft.resources.ResourceLocation;
+ import net.minecraft.server.level.ServerLevel;
++import net.minecraft.server.level.ServerPlayer;
+ import net.minecraft.sounds.SoundEvent;
+ import net.minecraft.tags.TagKey;
+ import net.minecraft.util.Mth;
+ import net.minecraft.util.RandomSource;
+ import net.minecraft.world.Difficulty;
+ import net.minecraft.world.DifficultyInstance;
+-import net.minecraft.world.InteractionHand;
++import net.minecraft.world.EnumHand;
+ import net.minecraft.world.InteractionResult;
+ import net.minecraft.world.damagesource.DamageSource;
+ import net.minecraft.world.entity.ai.attributes.AttributeModifier;
+@@ -47,7 +50,7 @@
+ import net.minecraft.world.entity.decoration.HangingEntity;
+ import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
+ import net.minecraft.world.entity.item.ItemEntity;
+-import net.minecraft.world.entity.monster.Enemy;
++import net.minecraft.world.entity.monster.IMonster;
+ import net.minecraft.world.entity.player.Player;
+ import net.minecraft.world.entity.vehicle.Boat;
+ import net.minecraft.world.item.ArmorItem;
+@@ -64,6 +67,7 @@
+ import net.minecraft.world.item.SwordItem;
+ import net.minecraft.world.item.enchantment.EnchantmentHelper;
+ import net.minecraft.world.level.GameRules;
++import net.minecraft.world.level.IMaterial;
+ import net.minecraft.world.level.Level;
+ import net.minecraft.world.level.LevelAccessor;
+ import net.minecraft.world.level.LevelReader;
+@@ -72,8 +76,19 @@
+ import net.minecraft.world.level.material.Fluid;
+ import net.minecraft.world.level.pathfinder.BlockPathTypes;
+ import net.minecraft.world.phys.AABB;
++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 Mob extends LivingEntity implements Targeting {
++
+ private static final EntityDataAccessor<Byte> DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE);
+ private static final int MOB_FLAG_NO_AI = 1;
+ private static final int MOB_FLAG_LEFTHANDED = 2;
+@@ -88,7 +103,7 @@
+ public static final float DEFAULT_EQUIPMENT_DROP_CHANCE = 0.085F;
+ public static final int PRESERVE_ITEM_DROP_CHANCE = 2;
+ public static final int UPDATE_GOAL_SELECTOR_EVERY_N_TICKS = 2;
+- private static final double DEFAULT_ATTACK_REACH = Math.sqrt(2.04F) - 0.6F;
++ private static final double DEFAULT_ATTACK_REACH = Math.sqrt(2.0399999618530273D) - 0.6000000238418579D;
+ public int ambientSoundTime;
+ protected int xpReward;
+ protected LookControl lookControl;
+@@ -96,31 +111,40 @@
+ protected JumpControl jumpControl;
+ private final BodyRotationControl bodyRotationControl;
+ protected PathNavigation navigation;
+- protected final GoalSelector goalSelector;
+- protected final GoalSelector targetSelector;
++ public GoalSelector goalSelector;
++ public GoalSelector targetSelector;
+ @Nullable
+ private LivingEntity target;
+ private final Sensing sensing;
+- private final NonNullList<ItemStack> handItems = NonNullList.withSize(2, ItemStack.EMPTY);
+- protected final float[] handDropChances = new float[2];
+- private final NonNullList<ItemStack> armorItems = NonNullList.withSize(4, ItemStack.EMPTY);
+- protected final float[] armorDropChances = new float[4];
++ private final NonNullList<ItemStack> handItems;
++ public final float[] handDropChances;
++ private final NonNullList<ItemStack> armorItems;
++ public final float[] armorDropChances;
+ private boolean canPickUpLoot;
+ private boolean persistenceRequired;
+- private final Map<BlockPathTypes, Float> pathfindingMalus = Maps.newEnumMap(BlockPathTypes.class);
++ private final Map<BlockPathTypes, Float> pathfindingMalus;
+ @Nullable
+- private ResourceLocation lootTable;
+- private long lootTableSeed;
++ public ResourceLocation lootTable;
++ public long lootTableSeed;
+ @Nullable
+ private Entity leashHolder;
+ private int delayedLeashHolderId;
+ @Nullable
+ private CompoundTag leashInfoTag;
+- private BlockPos restrictCenter = BlockPos.ZERO;
+- private float restrictRadius = -1.0F;
++ private BlockPos restrictCenter;
++ private float restrictRadius;
+
++ public boolean aware = true; // CraftBukkit
++
+ protected Mob(EntityType<? extends Mob> entityType, Level level) {
+ super(entityType, level);
++ this.handItems = NonNullList.withSize(2, ItemStack.EMPTY);
++ this.handDropChances = new float[2];
++ this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY);
++ this.armorDropChances = new float[4];
++ this.pathfindingMalus = Maps.newEnumMap(BlockPathTypes.class);
++ this.restrictCenter = BlockPos.ZERO;
++ this.restrictRadius = -1.0F;
+ this.goalSelector = new GoalSelector(level.getProfilerSupplier());
+ this.targetSelector = new GoalSelector(level.getProfilerSupplier());
+ this.lookControl = new LookControl(this);
+@@ -134,13 +158,19 @@
+ if (level != null && !level.isClientSide) {
+ this.registerGoals();
+ }
++
+ }
+
+- protected void registerGoals() {
++ // CraftBukkit start
++ public void setPersistenceRequired(boolean persistenceRequired) {
++ this.persistenceRequired = persistenceRequired;
+ }
++ // CraftBukkit end
+
++ protected void registerGoals() {}
++
+ public static AttributeSupplier.Builder createMobAttributes() {
+- return LivingEntity.createLivingAttributes().add(Attributes.FOLLOW_RANGE, 16.0).add(Attributes.ATTACK_KNOCKBACK);
++ return LivingEntity.createLivingAttributes().add(Attributes.FOLLOW_RANGE, 16.0D).add(Attributes.ATTACK_KNOCKBACK);
+ }
+
+ protected PathNavigation createNavigation(Level level) {
+@@ -152,29 +182,35 @@
+ }
+
+ public float getPathfindingMalus(BlockPathTypes nodeType) {
+- Mob mob1;
+- label17: {
+- if (this.getControlledVehicle() instanceof Mob mob && mob.shouldPassengersInheritMalus()) {
+- mob1 = mob;
+- break label17;
++ Mob entityinsentient;
++ label17:
++ {
++ Entity entity = this.getControlledVehicle();
++
++ if (entity instanceof Mob) {
++ Mob entityinsentient1 = (Mob) entity;
++
++ if (entityinsentient1.shouldPassengersInheritMalus()) {
++ entityinsentient = entityinsentient1;
++ break label17;
++ }
+ }
+
+- mob1 = this;
++ entityinsentient = this;
+ }
+
+- Float _float = mob1.pathfindingMalus.get(nodeType);
+- return _float == null ? nodeType.getMalus() : _float;
++ Float ofloat = (Float) entityinsentient.pathfindingMalus.get(nodeType);
++
++ return ofloat == null ? nodeType.getMalus() : ofloat;
+ }
+
+ public void setPathfindingMalus(BlockPathTypes nodeType, float malus) {
+ this.pathfindingMalus.put(nodeType, malus);
+ }
+
+- public void onPathfindingStart() {
+- }
++ public void onPathfindingStart() {}
+
+- public void onPathfindingDone() {
+- }
++ public void onPathfindingDone() {}
+
+ protected BodyRotationControl createBodyControl() {
+ return new BodyRotationControl(this);
+@@ -185,7 +221,15 @@
+ }
+
+ public MoveControl getMoveControl() {
+- return this.getControlledVehicle() instanceof Mob mob ? mob.getMoveControl() : this.moveControl;
++ Entity entity = this.getControlledVehicle();
++
++ if (entity instanceof Mob) {
++ Mob entityinsentient = (Mob) entity;
++
++ return entityinsentient.getMoveControl();
++ } else {
++ return this.moveControl;
++ }
+ }
+
+ public JumpControl getJumpControl() {
+@@ -193,18 +237,34 @@
+ }
+
+ public PathNavigation getNavigation() {
+- return this.getControlledVehicle() instanceof Mob mob ? mob.getNavigation() : this.navigation;
++ Entity entity = this.getControlledVehicle();
++
++ if (entity instanceof Mob) {
++ Mob entityinsentient = (Mob) entity;
++
++ return entityinsentient.getNavigation();
++ } else {
++ return this.navigation;
++ }
+ }
+
+ @Nullable
+ @Override
+ public LivingEntity getControllingPassenger() {
+- Entity firstPassenger = this.getFirstPassenger();
+- if (!this.isNoAi() && firstPassenger instanceof Mob mob && firstPassenger.canControlVehicle()) {
+- return mob;
++ Entity entity = this.getFirstPassenger();
++ Mob entityinsentient;
++
++ if (!this.isNoAi() && entity instanceof Mob) {
++ Mob entityinsentient1 = (Mob) entity;
++
++ if (entity.canControlVehicle()) {
++ entityinsentient = entityinsentient1;
++ return entityinsentient;
++ }
+ }
+
+- return null;
++ entityinsentient = null;
++ return entityinsentient;
+ }
+
+ public Sensing getSensing() {
+@@ -218,9 +278,40 @@
+ }
+
+ public void setTarget(@Nullable LivingEntity target) {
+- this.target = target;
++ // CraftBukkit start - fire event
++ setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true);
+ }
+
++ public boolean setTarget(LivingEntity 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
+ public boolean canAttackType(EntityType<?> type) {
+ return type != EntityType.GHAST;
+@@ -237,7 +328,7 @@
+ @Override
+ protected void defineSynchedData() {
+ super.defineSynchedData();
+- this.entityData.define(DATA_MOB_FLAGS_ID, (byte)0);
++ this.entityData.define(Mob.DATA_MOB_FLAGS_ID, (byte) 0);
+ }
+
+ public int getAmbientSoundInterval() {
+@@ -245,10 +336,12 @@
+ }
+
+ public void playAmbientSound() {
+- SoundEvent ambientSound = this.getAmbientSound();
+- if (ambientSound != null) {
+- this.playSound(ambientSound, this.getSoundVolume(), this.getVoicePitch());
++ SoundEvent soundeffect = this.getAmbientSound();
++
++ if (soundeffect != null) {
++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch());
+ }
++
+ }
+
+ @Override
+@@ -278,14 +371,16 @@
+ if (this.xpReward > 0) {
+ int i = this.xpReward;
+
+- for (int i1 = 0; i1 < this.armorItems.size(); i1++) {
+- if (!this.armorItems.get(i1).isEmpty() && this.armorDropChances[i1] <= 1.0F) {
++ int j;
++
++ for (j = 0; j < this.armorItems.size(); ++j) {
++ if (!((ItemStack) this.armorItems.get(j)).isEmpty() && this.armorDropChances[j] <= 1.0F) {
+ i += 1 + this.random.nextInt(3);
+ }
+ }
+
+- for (int i1x = 0; i1x < this.handItems.size(); i1x++) {
+- if (!this.handItems.get(i1x).isEmpty() && this.handDropChances[i1x] <= 1.0F) {
++ for (j = 0; j < this.handItems.size(); ++j) {
++ if (!((ItemStack) this.handItems.get(j)).isEmpty() && this.handDropChances[j] <= 1.0F) {
+ i += 1 + this.random.nextInt(3);
+ }
+ }
+@@ -298,17 +393,18 @@
+
+ public void spawnAnim() {
+ if (this.level().isClientSide) {
+- for (int i = 0; i < 20; i++) {
+- double d = this.random.nextGaussian() * 0.02;
+- double d1 = this.random.nextGaussian() * 0.02;
+- double d2 = this.random.nextGaussian() * 0.02;
+- double d3 = 10.0;
+- this.level()
+- .addParticle(ParticleTypes.POOF, this.getX(1.0) - d * 10.0, this.getRandomY() - d1 * 10.0, this.getRandomZ(1.0) - d2 * 10.0, d, d1, d2);
++ for (int i = 0; i < 20; ++i) {
++ double d0 = this.random.nextGaussian() * 0.02D;
++ double d1 = this.random.nextGaussian() * 0.02D;
++ double d2 = this.random.nextGaussian() * 0.02D;
++ double d3 = 10.0D;
++
++ this.level().addParticle(ParticleTypes.POOF, this.getX(1.0D) - d0 * 10.0D, this.getRandomY() - d1 * 10.0D, this.getRandomZ(1.0D) - d2 * 10.0D, d0, d1, d2);
+ }
+ } else {
+- this.level().broadcastEntityEvent(this, (byte)20);
++ this.level().broadcastEntityEvent(this, (byte) 20);
+ }
++
+ }
+
+ @Override
+@@ -318,6 +414,7 @@
+ } else {
+ super.handleEntityEvent(id);
+ }
++
+ }
+
+ @Override
+@@ -329,14 +426,16 @@
+ this.updateControlFlags();
+ }
+ }
++
+ }
+
+ protected void updateControlFlags() {
+ boolean flag = !(this.getControllingPassenger() instanceof Mob);
+ boolean flag1 = !(this.getVehicle() instanceof Boat);
+- this.goalSelector.setControlFlag(Goal.Flag.MOVE, flag);
+- this.goalSelector.setControlFlag(Goal.Flag.JUMP, flag && flag1);
+- this.goalSelector.setControlFlag(Goal.Flag.LOOK, flag);
++
++ this.goalSelector.setControlFlag(Goal.Type.MOVE, flag);
++ this.goalSelector.setControlFlag(Goal.Type.JUMP, flag && flag1);
++ this.goalSelector.setControlFlag(Goal.Type.LOOK, flag);
+ }
+
+ @Override
+@@ -350,62 +449,85 @@
+ return null;
+ }
+
++ // CraftBukkit start - Add delegate method
++ public SoundEvent getAmbientSound0() {
++ return getAmbientSound();
++ }
++ // CraftBukkit end
++
+ @Override
+ public void addAdditionalSaveData(CompoundTag compound) {
+ super.addAdditionalSaveData(compound);
+ compound.putBoolean("CanPickUpLoot", this.canPickUpLoot());
+ compound.putBoolean("PersistenceRequired", this.persistenceRequired);
+- ListTag list = new ListTag();
++ ListTag nbttaglist = new ListTag();
+
+- for (ItemStack itemStack : this.armorItems) {
+- CompoundTag compoundTag = new CompoundTag();
+- if (!itemStack.isEmpty()) {
+- itemStack.save(compoundTag);
+- }
++ CompoundTag nbttagcompound1;
+
+- list.add(compoundTag);
++ for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); nbttaglist.add(nbttagcompound1)) {
++ ItemStack itemstack = (ItemStack) iterator.next();
++
++ nbttagcompound1 = new CompoundTag();
++ if (!itemstack.isEmpty()) {
++ itemstack.save(nbttagcompound1);
++ }
+ }
+
+- compound.put("ArmorItems", list);
+- ListTag list1 = new ListTag();
++ compound.put("ArmorItems", nbttaglist);
++ ListTag nbttaglist1 = new ListTag();
+
+- for (ItemStack itemStack1 : this.handItems) {
+- CompoundTag compoundTag1 = new CompoundTag();
+- if (!itemStack1.isEmpty()) {
+- itemStack1.save(compoundTag1);
+- }
++ CompoundTag nbttagcompound2;
+
+- list1.add(compoundTag1);
++ for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); nbttaglist1.add(nbttagcompound2)) {
++ ItemStack itemstack1 = (ItemStack) iterator1.next();
++
++ nbttagcompound2 = new CompoundTag();
++ if (!itemstack1.isEmpty()) {
++ itemstack1.save(nbttagcompound2);
++ }
+ }
+
+- compound.put("HandItems", list1);
+- ListTag list2 = new ListTag();
++ compound.put("HandItems", nbttaglist1);
++ ListTag nbttaglist2 = new ListTag();
++ float[] afloat = this.armorDropChances;
++ int i = afloat.length;
+
+- for (float f : this.armorDropChances) {
+- list2.add(FloatTag.valueOf(f));
++ int j;
++
++ for (j = 0; j < i; ++j) {
++ float f = afloat[j];
++
++ nbttaglist2.add(FloatTag.valueOf(f));
+ }
+
+- compound.put("ArmorDropChances", list2);
+- ListTag list3 = new ListTag();
++ compound.put("ArmorDropChances", nbttaglist2);
++ ListTag nbttaglist3 = new ListTag();
++ float[] afloat1 = this.handDropChances;
+
+- for (float f1 : this.handDropChances) {
+- list3.add(FloatTag.valueOf(f1));
++ j = afloat1.length;
++
++ for (int k = 0; k < j; ++k) {
++ float f1 = afloat1[k];
++
++ nbttaglist3.add(FloatTag.valueOf(f1));
+ }
+
+- compound.put("HandDropChances", list3);
+- if (this.leashHolder != null) {
+- CompoundTag compoundTag1 = new CompoundTag();
++ compound.put("HandDropChances", nbttaglist3);
++ if (this.leashHolder != null && !this.leashHolder.pluginRemoved) { // CraftBukkit - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
++ nbttagcompound2 = new CompoundTag();
+ if (this.leashHolder instanceof LivingEntity) {
+- UUID uUID = this.leashHolder.getUUID();
+- compoundTag1.putUUID("UUID", uUID);
++ UUID uuid = this.leashHolder.getUUID();
++
++ nbttagcompound2.putUUID("UUID", uuid);
+ } else if (this.leashHolder instanceof HangingEntity) {
+- BlockPos pos = ((HangingEntity)this.leashHolder).getPos();
+- compoundTag1.putInt("X", pos.getX());
+- compoundTag1.putInt("Y", pos.getY());
+- compoundTag1.putInt("Z", pos.getZ());
++ BlockPos blockposition = ((HangingEntity) this.leashHolder).getPos();
++
++ nbttagcompound2.putInt("X", blockposition.getX());
++ nbttagcompound2.putInt("Y", blockposition.getY());
++ nbttagcompound2.putInt("Z", blockposition.getZ());
+ }
+
+- compound.put("Leash", compoundTag1);
++ compound.put("Leash", nbttagcompound2);
+ } else if (this.leashInfoTag != null) {
+ compound.put("Leash", this.leashInfoTag.copy());
+ }
+@@ -421,45 +543,59 @@
+ if (this.isNoAi()) {
+ compound.putBoolean("NoAI", this.isNoAi());
+ }
++
++ compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit
+ }
+
+ @Override
+ public void readAdditionalSaveData(CompoundTag compound) {
+ super.readAdditionalSaveData(compound);
++
++ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
+ if (compound.contains("CanPickUpLoot", 1)) {
+- this.setCanPickUpLoot(compound.getBoolean("CanPickUpLoot"));
++ boolean data = compound.getBoolean("CanPickUpLoot");
++ if (isLevelAtLeast(compound, 1) || data) {
++ this.setCanPickUpLoot(data);
++ }
+ }
+
+- this.persistenceRequired = compound.getBoolean("PersistenceRequired");
++ boolean data = compound.getBoolean("PersistenceRequired");
++ if (isLevelAtLeast(compound, 1) || data) {
++ this.persistenceRequired = data;
++ }
++ // CraftBukkit end
++ ListTag nbttaglist;
++ int i;
++
+ if (compound.contains("ArmorItems", 9)) {
+- ListTag list = compound.getList("ArmorItems", 10);
++ nbttaglist = compound.getList("ArmorItems", 10);
+
+- for (int i = 0; i < this.armorItems.size(); i++) {
+- this.armorItems.set(i, ItemStack.of(list.getCompound(i)));
++ for (i = 0; i < this.armorItems.size(); ++i) {
++ this.armorItems.set(i, ItemStack.of(nbttaglist.getCompound(i)));
+ }
+ }
+
+ if (compound.contains("HandItems", 9)) {
+- ListTag list = compound.getList("HandItems", 10);
++ nbttaglist = compound.getList("HandItems", 10);
+
+- for (int i = 0; i < this.handItems.size(); i++) {
+- this.handItems.set(i, ItemStack.of(list.getCompound(i)));
++ for (i = 0; i < this.handItems.size(); ++i) {
++ this.handItems.set(i, ItemStack.of(nbttaglist.getCompound(i)));
+ }
+ }
+
+ if (compound.contains("ArmorDropChances", 9)) {
+- ListTag list = compound.getList("ArmorDropChances", 5);
++ nbttaglist = compound.getList("ArmorDropChances", 5);
+
+- for (int i = 0; i < list.size(); i++) {
+- this.armorDropChances[i] = list.getFloat(i);
++ for (i = 0; i < nbttaglist.size(); ++i) {
++ this.armorDropChances[i] = nbttaglist.getFloat(i);
+ }
+ }
+
+ if (compound.contains("HandDropChances", 9)) {
+- ListTag list = compound.getList("HandDropChances", 5);
++ nbttaglist = compound.getList("HandDropChances", 5);
+
+- for (int i = 0; i < list.size(); i++) {
+- this.handDropChances[i] = list.getFloat(i);
++ for (i = 0; i < nbttaglist.size(); ++i) {
++ this.handDropChances[i] = nbttaglist.getFloat(i);
+ }
+ }
+
+@@ -474,6 +610,11 @@
+ }
+
+ this.setNoAi(compound.getBoolean("NoAI"));
++ // CraftBukkit start
++ if (compound.contains("Bukkit.Aware")) {
++ this.aware = compound.getBoolean("Bukkit.Aware");
++ }
++ // CraftBukkit end
+ }
+
+ @Override
+@@ -487,7 +628,7 @@
+ return this.lootTable == null ? this.getDefaultLootTable() : this.lootTable;
+ }
+
+- protected ResourceLocation getDefaultLootTable() {
++ public ResourceLocation getDefaultLootTable() {
+ return super.getLootTable();
+ }
+
+@@ -518,19 +659,16 @@
+ public void aiStep() {
+ super.aiStep();
+ this.level().getProfiler().push("looting");
+- if (!this.level().isClientSide
+- && this.canPickUpLoot()
+- && this.isAlive()
+- && !this.dead
+- && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
+- Vec3i pickupReach = this.getPickupReach();
++ if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
++ Vec3i baseblockposition = this.getPickupReach();
++ List<ItemEntity> list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ()));
++ Iterator iterator = list.iterator();
+
+- for (ItemEntity itemEntity : this.level()
+- .getEntitiesOfClass(
+- ItemEntity.class, this.getBoundingBox().inflate((double)pickupReach.getX(), (double)pickupReach.getY(), (double)pickupReach.getZ())
+- )) {
+- if (!itemEntity.isRemoved() && !itemEntity.getItem().isEmpty() && !itemEntity.hasPickUpDelay() && this.wantsToPickUp(itemEntity.getItem())) {
+- this.pickUpItem(itemEntity);
++ while (iterator.hasNext()) {
++ ItemEntity entityitem = (ItemEntity) iterator.next();
++
++ if (!entityitem.isRemoved() && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) {
++ this.pickUpItem(entityitem);
+ }
+ }
+ }
+@@ -539,45 +677,64 @@
+ }
+
+ protected Vec3i getPickupReach() {
+- return ITEM_PICKUP_REACH;
++ return Mob.ITEM_PICKUP_REACH;
+ }
+
+ protected void pickUpItem(ItemEntity itemEntity) {
+- ItemStack item = itemEntity.getItem();
+- ItemStack itemStack = this.equipItemIfPossible(item.copy());
+- if (!itemStack.isEmpty()) {
++ ItemStack itemstack = itemEntity.getItem();
++ ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), itemEntity); // CraftBukkit - add item
++
++ if (!itemstack1.isEmpty()) {
+ this.onItemPickup(itemEntity);
+- this.take(itemEntity, itemStack.getCount());
+- item.shrink(itemStack.getCount());
+- if (item.isEmpty()) {
++ this.take(itemEntity, itemstack1.getCount());
++ itemstack.shrink(itemstack1.getCount());
++ if (itemstack.isEmpty()) {
+ itemEntity.discard();
+ }
+ }
++
+ }
+
+ public ItemStack equipItemIfPossible(ItemStack stack) {
+- EquipmentSlot equipmentSlotForItem = getEquipmentSlotForItem(stack);
+- ItemStack itemBySlot = this.getItemBySlot(equipmentSlotForItem);
+- boolean canReplaceCurrentItem = this.canReplaceCurrentItem(stack, itemBySlot);
+- if (equipmentSlotForItem.isArmor() && !canReplaceCurrentItem) {
+- equipmentSlotForItem = EquipmentSlot.MAINHAND;
+- itemBySlot = this.getItemBySlot(equipmentSlotForItem);
+- canReplaceCurrentItem = itemBySlot.isEmpty();
++ // CraftBukkit start - add item
++ return this.equipItemIfPossible(stack, null);
++ }
++
++ public ItemStack equipItemIfPossible(ItemStack itemstack, ItemEntity entityitem) {
++ // CraftBukkit end
++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack);
++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot);
++ boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1);
++
++ if (enumitemslot.isArmor() && !flag) {
++ enumitemslot = EquipmentSlot.MAINHAND;
++ itemstack1 = this.getItemBySlot(enumitemslot);
++ flag = itemstack1.isEmpty();
+ }
+
+- if (canReplaceCurrentItem && this.canHoldItem(stack)) {
+- double d = (double)this.getEquipmentDropChance(equipmentSlotForItem);
+- if (!itemBySlot.isEmpty() && (double)Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) {
+- this.spawnAtLocation(itemBySlot);
++ // 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 (equipmentSlotForItem.isArmor() && stack.getCount() > 1) {
+- ItemStack itemStack = stack.copyWithCount(1);
+- this.setItemSlotAndDropWhenKilled(equipmentSlotForItem, itemStack);
+- return itemStack;
++ if (enumitemslot.isArmor() && itemstack.getCount() > 1) {
++ ItemStack itemstack2 = itemstack.copyWithCount(1);
++
++ this.setItemSlotAndDropWhenKilled(enumitemslot, itemstack2);
++ return itemstack2;
+ } else {
+- this.setItemSlotAndDropWhenKilled(equipmentSlotForItem, stack);
+- return stack;
++ this.setItemSlotAndDropWhenKilled(enumitemslot, itemstack);
++ return itemstack;
+ }
+ } else {
+ return ItemStack.EMPTY;
+@@ -598,6 +755,7 @@
+ case ARMOR:
+ this.armorDropChances[slot.getIndex()] = 2.0F;
+ }
++
+ }
+
+ protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) {
+@@ -607,58 +765,61 @@
+ if (!(existing.getItem() instanceof SwordItem)) {
+ return true;
+ } else {
+- SwordItem swordItem = (SwordItem)candidate.getItem();
+- SwordItem swordItem1 = (SwordItem)existing.getItem();
+- return swordItem.getDamage() != swordItem1.getDamage()
+- ? swordItem.getDamage() > swordItem1.getDamage()
+- : this.canReplaceEqualItem(candidate, existing);
++ SwordItem itemsword = (SwordItem) candidate.getItem();
++ SwordItem itemsword1 = (SwordItem) existing.getItem();
++
++ return itemsword.getDamage() != itemsword1.getDamage() ? itemsword.getDamage() > itemsword1.getDamage() : this.canReplaceEqualItem(candidate, existing);
+ }
+ } else if (candidate.getItem() instanceof BowItem && existing.getItem() instanceof BowItem) {
+ return this.canReplaceEqualItem(candidate, existing);
+ } else if (candidate.getItem() instanceof CrossbowItem && existing.getItem() instanceof CrossbowItem) {
+ return this.canReplaceEqualItem(candidate, existing);
+- } else if (candidate.getItem() instanceof ArmorItem armorItem) {
+- if (EnchantmentHelper.hasBindingCurse(existing)) {
+- return false;
+- } else if (!(existing.getItem() instanceof ArmorItem)) {
+- return true;
+- } else {
+- ArmorItem armorItem1 = (ArmorItem)existing.getItem();
+- if (armorItem.getDefense() != armorItem1.getDefense()) {
+- return armorItem.getDefense() > armorItem1.getDefense();
+- } else {
+- return armorItem.getToughness() != armorItem1.getToughness()
+- ? armorItem.getToughness() > armorItem1.getToughness()
+- : this.canReplaceEqualItem(candidate, existing);
+- }
+- }
+ } else {
+- if (candidate.getItem() instanceof DiggerItem) {
+- if (existing.getItem() instanceof BlockItem) {
++ Item item = candidate.getItem();
++
++ if (item instanceof ArmorItem) {
++ ArmorItem itemarmor = (ArmorItem) item;
++
++ if (EnchantmentHelper.hasBindingCurse(existing)) {
++ return false;
++ } else if (!(existing.getItem() instanceof ArmorItem)) {
+ return true;
+- }
++ } else {
++ ArmorItem itemarmor1 = (ArmorItem) existing.getItem();
+
+- if (existing.getItem() instanceof DiggerItem diggerItem) {
+- DiggerItem diggerItem1 = (DiggerItem)candidate.getItem();
+- if (diggerItem1.getAttackDamage() != diggerItem.getAttackDamage()) {
+- return diggerItem1.getAttackDamage() > diggerItem.getAttackDamage();
++ return itemarmor.getDefense() != itemarmor1.getDefense() ? itemarmor.getDefense() > itemarmor1.getDefense() : (itemarmor.getToughness() != itemarmor1.getToughness() ? itemarmor.getToughness() > itemarmor1.getToughness() : this.canReplaceEqualItem(candidate, existing));
++ }
++ } else {
++ if (candidate.getItem() instanceof DiggerItem) {
++ if (existing.getItem() instanceof BlockItem) {
++ return true;
+ }
+
+- return this.canReplaceEqualItem(candidate, existing);
++ Item item1 = existing.getItem();
++
++ if (item1 instanceof DiggerItem) {
++ DiggerItem itemtool = (DiggerItem) item1;
++ DiggerItem itemtool1 = (DiggerItem) candidate.getItem();
++
++ if (itemtool1.getAttackDamage() != itemtool.getAttackDamage()) {
++ return itemtool1.getAttackDamage() > itemtool.getAttackDamage();
++ }
++
++ return this.canReplaceEqualItem(candidate, existing);
++ }
+ }
+- }
+
+- return false;
++ return false;
++ }
+ }
+ }
+
+ public boolean canReplaceEqualItem(ItemStack candidate, ItemStack existing) {
+- return candidate.getDamageValue() < existing.getDamageValue()
+- || candidate.hasTag() && !existing.hasTag()
+- || candidate.hasTag()
+- && existing.hasTag()
+- && candidate.getTag().getAllKeys().stream().anyMatch(stack -> !stack.equals("Damage"))
+- && !existing.getTag().getAllKeys().stream().anyMatch(stack -> !stack.equals("Damage"));
++ return candidate.getDamageValue() >= existing.getDamageValue() && (!candidate.hasTag() || existing.hasTag()) ? (candidate.hasTag() && existing.hasTag() ? candidate.getTag().getAllKeys().stream().anyMatch((s) -> {
++ return !s.equals("Damage");
++ }) && !existing.getTag().getAllKeys().stream().anyMatch((s) -> {
++ return !s.equals("Damage");
++ }) : false) : true;
+ }
+
+ public boolean canHoldItem(ItemStack stack) {
+@@ -686,23 +847,27 @@
+ if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
+ this.discard();
+ } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) {
+- Entity nearestPlayer = this.level().getNearestPlayer(this, -1.0);
+- if (nearestPlayer != null) {
+- double d = nearestPlayer.distanceToSqr(this);
+- int despawnDistance = this.getType().getCategory().getDespawnDistance();
+- int i = despawnDistance * despawnDistance;
+- if (d > (double)i && this.removeWhenFarAway(d)) {
++ Player entityhuman = this.level().getNearestPlayer(this, -1.0D);
++
++ if (entityhuman != null) {
++ double d0 = entityhuman.distanceToSqr((Entity) this);
++ int i = this.getType().getCategory().getDespawnDistance();
++ int j = i * i;
++
++ if (d0 > (double) j && this.removeWhenFarAway(d0)) {
+ this.discard();
+ }
+
+- int noDespawnDistance = this.getType().getCategory().getNoDespawnDistance();
+- int i1 = noDespawnDistance * noDespawnDistance;
+- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d > (double)i1 && this.removeWhenFarAway(d)) {
++ 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();
+- } else if (d < (double)i1) {
++ } else if (d0 < (double) l) {
+ this.noActionTime = 0;
+ }
+ }
++
+ } else {
+ this.noActionTime = 0;
+ }
+@@ -710,11 +875,13 @@
+
+ @Override
+ protected final void serverAiStep() {
+- this.noActionTime++;
++ ++this.noActionTime;
++ if (!this.aware) return; // CraftBukkit
+ this.level().getProfiler().push("sensing");
+ this.sensing.tick();
+ this.level().getProfiler().pop();
+ int i = this.level().getServer().getTickCount() + this.getId();
++
+ if (i % 2 != 0 && this.tickCount > 1) {
+ this.level().getProfiler().push("targetSelector");
+ this.targetSelector.tickRunningGoals(false);
+@@ -753,8 +920,7 @@
+ DebugPackets.sendGoalSelector(this.level(), this, this.goalSelector);
+ }
+
+- protected void customServerAiStep() {
+- }
++ protected void customServerAiStep() {}
+
+ public int getMaxHeadXRot() {
+ return 40;
+@@ -769,41 +935,47 @@
+ }
+
+ public void lookAt(Entity entity, float maxYRotIncrease, float maxXRotIncrease) {
+- double d = entity.getX() - this.getX();
++ double d0 = entity.getX() - this.getX();
+ double d1 = entity.getZ() - this.getZ();
+ double d2;
+- if (entity instanceof LivingEntity livingEntity) {
+- d2 = livingEntity.getEyeY() - this.getEyeY();
++
++ if (entity instanceof LivingEntity) {
++ LivingEntity entityliving = (LivingEntity) entity;
++
++ d2 = entityliving.getEyeY() - this.getEyeY();
+ } else {
+- d2 = (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0 - this.getEyeY();
++ d2 = (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D - this.getEyeY();
+ }
+
+- double squareRoot = Math.sqrt(d * d + d1 * d1);
+- float f = (float)(Mth.atan2(d1, d) * 180.0F / (float)Math.PI) - 90.0F;
+- float f1 = (float)(-(Mth.atan2(d2, squareRoot) * 180.0F / (float)Math.PI));
+- this.setXRot(this.rotlerp(this.getXRot(), f1, maxXRotIncrease));
+- this.setYRot(this.rotlerp(this.getYRot(), f, maxYRotIncrease));
++ double d3 = Math.sqrt(d0 * d0 + d1 * d1);
++ float f2 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F;
++ float f3 = (float) (-(Mth.atan2(d2, d3) * 57.2957763671875D));
++
++ this.setXRot(this.rotlerp(this.getXRot(), f3, maxXRotIncrease));
++ this.setYRot(this.rotlerp(this.getYRot(), f2, maxYRotIncrease));
+ }
+
+ private float rotlerp(float angle, float targetAngle, float maxIncrease) {
+- float f = Mth.wrapDegrees(targetAngle - angle);
+- if (f > maxIncrease) {
+- f = maxIncrease;
++ float f3 = Mth.wrapDegrees(targetAngle - angle);
++
++ if (f3 > maxIncrease) {
++ f3 = maxIncrease;
+ }
+
+- if (f < -maxIncrease) {
+- f = -maxIncrease;
++ if (f3 < -maxIncrease) {
++ f3 = -maxIncrease;
+ }
+
+- return angle + f;
++ return angle + f3;
+ }
+
+- public static boolean checkMobSpawnRules(EntityType<? extends Mob> type, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) {
+- BlockPos blockPos = pos.below();
+- return spawnType == MobSpawnType.SPAWNER || level.getBlockState(blockPos).isValidSpawn(level, blockPos, type);
++ public static boolean checkMobSpawnRules(EntityType<? extends Mob> type, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) {
++ BlockPos blockposition1 = pos.below();
++
++ return spawnType == EnumMobSpawn.SPAWNER || level.getBlockState(blockposition1).isValidSpawn(level, blockposition1, type);
+ }
+
+- public boolean checkSpawnRules(LevelAccessor level, MobSpawnType reason) {
++ public boolean checkSpawnRules(LevelAccessor level, EnumMobSpawn reason) {
+ return true;
+ }
+
+@@ -824,13 +996,14 @@
+ if (this.getTarget() == null) {
+ return 3;
+ } else {
+- int i = (int)(this.getHealth() - this.getMaxHealth() * 0.33F);
+- int var2 = i - (3 - this.level().getDifficulty().getId()) * 4;
+- if (var2 < 0) {
+- var2 = 0;
++ int i = (int) (this.getHealth() - this.getMaxHealth() * 0.33F);
++
++ i -= (3 - this.level().getDifficulty().getId()) * 4;
++ if (i < 0) {
++ i = 0;
+ }
+
+- return var2 + 3;
++ return i + 3;
+ }
+ }
+
+@@ -848,9 +1021,9 @@
+ public ItemStack getItemBySlot(EquipmentSlot slot) {
+ switch (slot.getType()) {
+ case HAND:
+- return this.handItems.get(slot.getIndex());
++ return (ItemStack) this.handItems.get(slot.getIndex());
+ case ARMOR:
+- return this.armorItems.get(slot.getIndex());
++ return (ItemStack) this.armorItems.get(slot.getIndex());
+ default:
+ return ItemStack.EMPTY;
+ }
+@@ -861,80 +1034,98 @@
+ this.verifyEquippedItem(stack);
+ switch (slot.getType()) {
+ case HAND:
+- this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack);
++ this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack);
+ break;
+ case ARMOR:
+- this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack);
++ this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack);
+ }
++
+ }
+
+ @Override
+ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) {
+ super.dropCustomDeathLoot(source, looting, recentlyHit);
++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values();
++ int j = aenumitemslot.length;
+
+- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
+- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
+- float equipmentDropChance = this.getEquipmentDropChance(equipmentSlot);
+- boolean flag = equipmentDropChance > 1.0F;
+- if (!itemBySlot.isEmpty()
+- && !EnchantmentHelper.hasVanishingCurse(itemBySlot)
+- && (recentlyHit || flag)
+- && Math.max(this.random.nextFloat() - (float)looting * 0.01F, 0.0F) < equipmentDropChance) {
+- if (!flag && itemBySlot.isDamageableItem()) {
+- itemBySlot.setDamageValue(
+- itemBySlot.getMaxDamage() - this.random.nextInt(1 + this.random.nextInt(Math.max(itemBySlot.getMaxDamage() - 3, 1)))
+- );
++ for (int k = 0; k < j; ++k) {
++ EquipmentSlot enumitemslot = aenumitemslot[k];
++ ItemStack itemstack = this.getItemBySlot(enumitemslot);
++ float f = this.getEquipmentDropChance(enumitemslot);
++ boolean flag1 = f > 1.0F;
++
++ if (!itemstack.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemstack) && (recentlyHit || flag1) && Math.max(this.random.nextFloat() - (float) looting * 0.01F, 0.0F) < f) {
++ if (!flag1 && itemstack.isDamageableItem()) {
++ itemstack.setDamageValue(itemstack.getMaxDamage() - this.random.nextInt(1 + this.random.nextInt(Math.max(itemstack.getMaxDamage() - 3, 1))));
+ }
+
+- this.spawnAtLocation(itemBySlot);
+- this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
++ this.spawnAtLocation(itemstack);
++ this.setItemSlot(enumitemslot, ItemStack.EMPTY);
+ }
+ }
++
+ }
+
+ protected float getEquipmentDropChance(EquipmentSlot slot) {
+- return switch (slot.getType()) {
+- case HAND -> this.handDropChances[slot.getIndex()];
+- case ARMOR -> this.armorDropChances[slot.getIndex()];
+- default -> 0.0F;
+- };
++ float f;
++
++ switch (slot.getType()) {
++ case HAND:
++ f = this.handDropChances[slot.getIndex()];
++ break;
++ case ARMOR:
++ f = this.armorDropChances[slot.getIndex()];
++ break;
++ default:
++ f = 0.0F;
++ }
++
++ return f;
+ }
+
+ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) {
+ if (random.nextFloat() < 0.15F * difficulty.getSpecialMultiplier()) {
+- int randomInt = random.nextInt(2);
++ int i = random.nextInt(2);
+ float f = this.level().getDifficulty() == Difficulty.HARD ? 0.1F : 0.25F;
++
+ if (random.nextFloat() < 0.095F) {
+- randomInt++;
++ ++i;
+ }
+
+ if (random.nextFloat() < 0.095F) {
+- randomInt++;
++ ++i;
+ }
+
+ if (random.nextFloat() < 0.095F) {
+- randomInt++;
++ ++i;
+ }
+
+ boolean flag = true;
++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values();
++ int j = aenumitemslot.length;
+
+- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
+- if (equipmentSlot.getType() == EquipmentSlot.Type.ARMOR) {
+- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
++ for (int k = 0; k < j; ++k) {
++ EquipmentSlot enumitemslot = aenumitemslot[k];
++
++ if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) {
++ ItemStack itemstack = this.getItemBySlot(enumitemslot);
++
+ if (!flag && random.nextFloat() < f) {
+ break;
+ }
+
+ flag = false;
+- if (itemBySlot.isEmpty()) {
+- Item equipmentForSlot = getEquipmentForSlot(equipmentSlot, randomInt);
+- if (equipmentForSlot != null) {
+- this.setItemSlot(equipmentSlot, new ItemStack(equipmentForSlot));
++ if (itemstack.isEmpty()) {
++ Item item = getEquipmentForSlot(enumitemslot, i);
++
++ if (item != null) {
++ this.setItemSlot(enumitemslot, new ItemStack(item));
+ }
+ }
+ }
+ }
+ }
++
+ }
+
+ @Nullable
+@@ -994,42 +1185,44 @@
+ }
+
+ protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) {
+- float specialMultiplier = difficulty.getSpecialMultiplier();
+- this.enchantSpawnedWeapon(random, specialMultiplier);
++ float f = difficulty.getSpecialMultiplier();
+
+- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
+- if (equipmentSlot.getType() == EquipmentSlot.Type.ARMOR) {
+- this.enchantSpawnedArmor(random, specialMultiplier, equipmentSlot);
++ this.enchantSpawnedWeapon(random, f);
++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values();
++ int i = aenumitemslot.length;
++
++ for (int j = 0; j < i; ++j) {
++ EquipmentSlot enumitemslot = aenumitemslot[j];
++
++ if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) {
++ this.enchantSpawnedArmor(random, f, enumitemslot);
+ }
+ }
++
+ }
+
+ protected void enchantSpawnedWeapon(RandomSource random, float chanceMultiplier) {
+ if (!this.getMainHandItem().isEmpty() && random.nextFloat() < 0.25F * chanceMultiplier) {
+- this.setItemSlot(
+- EquipmentSlot.MAINHAND,
+- EnchantmentHelper.enchantItem(random, this.getMainHandItem(), (int)(5.0F + chanceMultiplier * (float)random.nextInt(18)), false)
+- );
++ this.setItemSlot(EquipmentSlot.MAINHAND, EnchantmentHelper.enchantItem(random, this.getMainHandItem(), (int) (5.0F + chanceMultiplier * (float) random.nextInt(18)), false));
+ }
++
+ }
+
+ protected void enchantSpawnedArmor(RandomSource random, float chanceMultiplier, EquipmentSlot slot) {
+- ItemStack itemBySlot = this.getItemBySlot(slot);
+- if (!itemBySlot.isEmpty() && random.nextFloat() < 0.5F * chanceMultiplier) {
+- this.setItemSlot(slot, EnchantmentHelper.enchantItem(random, itemBySlot, (int)(5.0F + chanceMultiplier * (float)random.nextInt(18)), false));
++ ItemStack itemstack = this.getItemBySlot(slot);
++
++ if (!itemstack.isEmpty() && random.nextFloat() < 0.5F * chanceMultiplier) {
++ this.setItemSlot(slot, EnchantmentHelper.enchantItem(random, itemstack, (int) (5.0F + chanceMultiplier * (float) random.nextInt(18)), false));
+ }
++
+ }
+
+ @Nullable
+- public SpawnGroupData finalizeSpawn(
+- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag
+- ) {
+- RandomSource random = level.getRandom();
+- this.getAttribute(Attributes.FOLLOW_RANGE)
+- .addPermanentModifier(
+- new AttributeModifier("Random spawn bonus", random.triangle(0.0, 0.11485000000000001), AttributeModifier.Operation.MULTIPLY_BASE)
+- );
+- if (random.nextFloat() < 0.05F) {
++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) {
++ RandomSource randomsource = level.getRandom();
++
++ this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random spawn bonus", randomsource.triangle(0.0D, 0.11485000000000001D), AttributeModifier.Operation.MULTIPLY_BASE));
++ if (randomsource.nextFloat() < 0.05F) {
+ this.setLeftHanded(true);
+ } else {
+ this.setLeftHanded(false);
+@@ -1050,6 +1243,7 @@
+ case ARMOR:
+ this.armorDropChances[slot.getIndex()] = chance;
+ }
++
+ }
+
+ public boolean canPickUpLoot() {
+@@ -1062,8 +1256,9 @@
+
+ @Override
+ public boolean canTakeItem(ItemStack itemstack) {
+- EquipmentSlot equipmentSlotForItem = getEquipmentSlotForItem(itemstack);
+- return this.getItemBySlot(equipmentSlotForItem).isEmpty() && this.canPickUpLoot();
++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack);
++
++ return this.getItemBySlot(enumitemslot).isEmpty() && this.canPickUpLoot();
+ }
+
+ public boolean isPersistenceRequired() {
+@@ -1071,23 +1266,30 @@
+ }
+
+ @Override
+- public final InteractionResult interact(Player player, InteractionHand hand) {
++ public final InteractionResult interact(Player player, EnumHand hand) {
+ if (!this.isAlive()) {
+ return InteractionResult.PASS;
+ } else if (this.getLeashHolder() == player) {
++ // CraftBukkit start - fire PlayerUnleashEntityEvent
++ if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand).isCancelled()) {
++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder()));
++ return InteractionResult.PASS;
++ }
++ // CraftBukkit end
+ this.dropLeash(true, !player.getAbilities().instabuild);
+ this.gameEvent(GameEvent.ENTITY_INTERACT, player);
+ return InteractionResult.sidedSuccess(this.level().isClientSide);
+ } else {
+- InteractionResult interactionResult = this.checkAndHandleImportantInteractions(player, hand);
+- if (interactionResult.consumesAction()) {
++ InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand);
++
++ if (enuminteractionresult.consumesAction()) {
+ this.gameEvent(GameEvent.ENTITY_INTERACT, player);
+- return interactionResult;
++ return enuminteractionresult;
+ } else {
+- interactionResult = this.mobInteract(player, hand);
+- if (interactionResult.consumesAction()) {
++ enuminteractionresult = this.mobInteract(player, hand);
++ if (enuminteractionresult.consumesAction()) {
+ this.gameEvent(GameEvent.ENTITY_INTERACT, player);
+- return interactionResult;
++ return enuminteractionresult;
+ } else {
+ return super.interact(player, hand);
+ }
+@@ -1095,27 +1297,36 @@
+ }
+ }
+
+- private InteractionResult checkAndHandleImportantInteractions(Player player, InteractionHand hand) {
+- ItemStack itemInHand = player.getItemInHand(hand);
+- if (itemInHand.is(Items.LEAD) && this.canBeLeashed(player)) {
++ private InteractionResult checkAndHandleImportantInteractions(Player player, EnumHand hand) {
++ ItemStack itemstack = player.getItemInHand(hand);
++
++ if (itemstack.is(Items.LEAD) && this.canBeLeashed(player)) {
++ // CraftBukkit start - fire PlayerLeashEntityEvent
++ if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) {
++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder()));
++ return InteractionResult.PASS;
++ }
++ // CraftBukkit end
+ this.setLeashedTo(player, true);
+- itemInHand.shrink(1);
++ itemstack.shrink(1);
+ return InteractionResult.sidedSuccess(this.level().isClientSide);
+ } else {
+- if (itemInHand.is(Items.NAME_TAG)) {
+- InteractionResult interactionResult = itemInHand.interactLivingEntity(player, this, hand);
+- if (interactionResult.consumesAction()) {
+- return interactionResult;
++ if (itemstack.is(Items.NAME_TAG)) {
++ InteractionResult enuminteractionresult = itemstack.interactLivingEntity(player, this, hand);
++
++ if (enuminteractionresult.consumesAction()) {
++ return enuminteractionresult;
+ }
+ }
+
+- if (itemInHand.getItem() instanceof SpawnEggItem) {
++ if (itemstack.getItem() instanceof SpawnEggItem) {
+ if (this.level() instanceof ServerLevel) {
+- SpawnEggItem spawnEggItem = (SpawnEggItem)itemInHand.getItem();
+- Optional<Mob> optional = spawnEggItem.spawnOffspringFromSpawnEgg(
+- player, this, (EntityType<? extends Mob>)this.getType(), (ServerLevel)this.level(), this.position(), itemInHand
+- );
+- optional.ifPresent(mob -> this.onOffspringSpawnedFromEgg(player, mob));
++ SpawnEggItem itemmonsteregg = (SpawnEggItem) itemstack.getItem();
++ Optional<Mob> optional = itemmonsteregg.spawnOffspringFromSpawnEgg(player, this, (EntityType<? extends Mob>) this.getType(), (ServerLevel) this.level(), this.position(), itemstack); // CraftBukkit - decompile error
++
++ optional.ifPresent((entityinsentient) -> {
++ this.onOffspringSpawnedFromEgg(player, entityinsentient);
++ });
+ return optional.isPresent() ? InteractionResult.SUCCESS : InteractionResult.PASS;
+ } else {
+ return InteractionResult.CONSUME;
+@@ -1126,10 +1337,9 @@
+ }
+ }
+
+- protected void onOffspringSpawnedFromEgg(Player player, Mob child) {
+- }
++ protected void onOffspringSpawnedFromEgg(Player player, Mob child) {}
+
+- protected InteractionResult mobInteract(Player player, InteractionHand hand) {
++ protected InteractionResult mobInteract(Player player, EnumHand hand) {
+ return InteractionResult.PASS;
+ }
+
+@@ -1138,12 +1348,12 @@
+ }
+
+ public boolean isWithinRestriction(BlockPos pos) {
+- return this.restrictRadius == -1.0F || this.restrictCenter.distSqr(pos) < (double)(this.restrictRadius * this.restrictRadius);
++ return this.restrictRadius == -1.0F ? true : this.restrictCenter.distSqr(pos) < (double) (this.restrictRadius * this.restrictRadius);
+ }
+
+ public void restrictTo(BlockPos pos, int distance) {
+ this.restrictCenter = pos;
+- this.restrictRadius = (float)distance;
++ this.restrictRadius = (float) distance;
+ }
+
+ public BlockPos getRestrictCenter() {
+@@ -1162,49 +1372,67 @@
+ return this.restrictRadius != -1.0F;
+ }
+
++ // CraftBukkit start
+ @Nullable
+ public <T extends Mob> T convertTo(EntityType<T> entityType, boolean transferInventory) {
++ return this.convertTo(entityType, transferInventory, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT);
++ }
++
++ @Nullable
++ public <T extends Mob> T convertTo(EntityType<T> entitytypes, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) {
++ // CraftBukkit end
+ if (this.isRemoved()) {
+ return null;
+ } else {
+- T mob = (T)entityType.create(this.level());
+- if (mob == null) {
++ T t0 = entitytypes.create(this.level()); // CraftBukkit - decompile error
++
++ if (t0 == null) {
+ return null;
+ } else {
+- mob.copyPosition(this);
+- mob.setBaby(this.isBaby());
+- mob.setNoAi(this.isNoAi());
++ t0.copyPosition(this);
++ t0.setBaby(this.isBaby());
++ t0.setNoAi(this.isNoAi());
+ if (this.hasCustomName()) {
+- mob.setCustomName(this.getCustomName());
+- mob.setCustomNameVisible(this.isCustomNameVisible());
++ t0.setCustomName(this.getCustomName());
++ t0.setCustomNameVisible(this.isCustomNameVisible());
+ }
+
+ if (this.isPersistenceRequired()) {
+- mob.setPersistenceRequired();
++ t0.setPersistenceRequired();
+ }
+
+- mob.setInvulnerable(this.isInvulnerable());
+- if (transferInventory) {
+- mob.setCanPickUpLoot(this.canPickUpLoot());
++ t0.setInvulnerable(this.isInvulnerable());
++ if (flag) {
++ t0.setCanPickUpLoot(this.canPickUpLoot());
++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values();
++ int i = aenumitemslot.length;
+
+- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
+- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
+- if (!itemBySlot.isEmpty()) {
+- mob.setItemSlot(equipmentSlot, itemBySlot.copyAndClear());
+- mob.setDropChance(equipmentSlot, this.getEquipmentDropChance(equipmentSlot));
++ for (int j = 0; j < i; ++j) {
++ EquipmentSlot enumitemslot = aenumitemslot[j];
++ ItemStack itemstack = this.getItemBySlot(enumitemslot);
++
++ if (!itemstack.isEmpty()) {
++ t0.setItemSlot(enumitemslot, itemstack.copyAndClear());
++ t0.setDropChance(enumitemslot, this.getEquipmentDropChance(enumitemslot));
+ }
+ }
+ }
+
+- this.level().addFreshEntity(mob);
++ // CraftBukkit start
++ if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) {
++ return null;
++ }
++ this.level().addFreshEntity(t0, spawnReason);
++ // CraftBukkit end
+ if (this.isPassenger()) {
+- Entity vehicle = this.getVehicle();
++ Entity entity = this.getVehicle();
++
+ this.stopRiding();
+- mob.startRiding(vehicle, true);
++ t0.startRiding(entity, true);
+ }
+
+ this.discard();
+- return mob;
++ return t0;
+ }
+ }
+ }
+@@ -1216,8 +1444,10 @@
+
+ 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
+ }
++
+ }
+ }
+
+@@ -1226,17 +1456,20 @@
+ this.leashHolder = null;
+ this.leashInfoTag = null;
+ if (!this.level().isClientSide && dropLeash) {
+- this.spawnAtLocation(Items.LEAD);
++ this.forceDrops = true; // CraftBukkit
++ this.spawnAtLocation((IMaterial) Items.LEAD);
++ this.forceDrops = false; // CraftBukkit
+ }
+
+ if (!this.level().isClientSide && broadcastPacket && this.level() instanceof ServerLevel) {
+- ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, null));
++ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, (Entity) null));
+ }
+ }
++
+ }
+
+ public boolean canBeLeashed(Player player) {
+- return !this.isLeashed() && !(this instanceof Enemy);
++ return !this.isLeashed() && !(this instanceof IMonster);
+ }
+
+ public boolean isLeashed() {
+@@ -1256,12 +1489,13 @@
+ this.leashHolder = leashHolder;
+ this.leashInfoTag = null;
+ if (!this.level().isClientSide && broadcastPacket && this.level() instanceof ServerLevel) {
+- ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, this.leashHolder));
++ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, this.leashHolder));
+ }
+
+ if (this.isPassenger()) {
+ this.stopRiding();
+ }
++
+ }
+
+ public void setDelayedLeashHolderId(int leashHolderID) {
+@@ -1271,34 +1505,41 @@
+
+ @Override
+ public boolean startRiding(Entity entity, boolean force) {
+- boolean flag = super.startRiding(entity, force);
+- if (flag && this.isLeashed()) {
++ boolean flag1 = super.startRiding(entity, force);
++
++ if (flag1 && this.isLeashed()) {
++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit
+ this.dropLeash(true, true);
+ }
+
+- return flag;
++ return flag1;
+ }
+
+ private void restoreLeashFromSave() {
+ if (this.leashInfoTag != null && this.level() instanceof ServerLevel) {
+ if (this.leashInfoTag.hasUUID("UUID")) {
+- UUID uUID = this.leashInfoTag.getUUID("UUID");
+- Entity entity = ((ServerLevel)this.level()).getEntity(uUID);
++ UUID uuid = this.leashInfoTag.getUUID("UUID");
++ Entity entity = ((ServerLevel) this.level()).getEntity(uuid);
++
+ if (entity != null) {
+ this.setLeashedTo(entity, true);
+ return;
+ }
+ } else if (this.leashInfoTag.contains("X", 99) && this.leashInfoTag.contains("Y", 99) && this.leashInfoTag.contains("Z", 99)) {
+- BlockPos blockPos = NbtUtils.readBlockPos(this.leashInfoTag);
+- this.setLeashedTo(LeashFenceKnotEntity.getOrCreateKnot(this.level(), blockPos), true);
++ BlockPos blockposition = NbtUtils.readBlockPos(this.leashInfoTag);
++
++ this.setLeashedTo(LeashFenceKnotEntity.getOrCreateKnot(this.level(), blockposition), true);
+ return;
+ }
+
+ if (this.tickCount > 100) {
+- this.spawnAtLocation(Items.LEAD);
++ this.forceDrops = true; // CraftBukkit
++ this.spawnAtLocation((IMaterial) Items.LEAD);
++ this.forceDrops = false; // CraftBukkit
+ this.leashInfoTag = null;
+ }
+ }
++
+ }
+
+ @Override
+@@ -1307,34 +1548,36 @@
+ }
+
+ public void setNoAi(boolean noAi) {
+- byte b = this.entityData.get(DATA_MOB_FLAGS_ID);
+- this.entityData.set(DATA_MOB_FLAGS_ID, noAi ? (byte)(b | 1) : (byte)(b & -2));
++ byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID);
++
++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, noAi ? (byte) (b0 | 1) : (byte) (b0 & -2));
+ }
+
+ public void setLeftHanded(boolean leftHanded) {
+- byte b = this.entityData.get(DATA_MOB_FLAGS_ID);
+- this.entityData.set(DATA_MOB_FLAGS_ID, leftHanded ? (byte)(b | 2) : (byte)(b & -3));
++ byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID);
++
++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, leftHanded ? (byte) (b0 | 2) : (byte) (b0 & -3));
+ }
+
+ public void setAggressive(boolean aggressive) {
+- byte b = this.entityData.get(DATA_MOB_FLAGS_ID);
+- this.entityData.set(DATA_MOB_FLAGS_ID, aggressive ? (byte)(b | 4) : (byte)(b & -5));
++ byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID);
++
++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, aggressive ? (byte) (b0 | 4) : (byte) (b0 & -5));
+ }
+
+ public boolean isNoAi() {
+- return (this.entityData.get(DATA_MOB_FLAGS_ID) & 1) != 0;
++ return ((Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID) & 1) != 0;
+ }
+
+ public boolean isLeftHanded() {
+- return (this.entityData.get(DATA_MOB_FLAGS_ID) & 2) != 0;
++ return ((Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID) & 2) != 0;
+ }
+
+ public boolean isAggressive() {
+- return (this.entityData.get(DATA_MOB_FLAGS_ID) & 4) != 0;
++ return ((Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID) & 4) != 0;
+ }
+
+- public void setBaby(boolean baby) {
+- }
++ public void setBaby(boolean baby) {}
+
+ @Override
+ public HumanoidArm getMainArm() {
+@@ -1346,54 +1589,56 @@
+ }
+
+ protected AABB getAttackBoundingBox() {
+- Entity vehicle = this.getVehicle();
+- AABB aABB;
+- if (vehicle != null) {
+- AABB boundingBox = vehicle.getBoundingBox();
+- AABB boundingBox1 = this.getBoundingBox();
+- aABB = new AABB(
+- Math.min(boundingBox1.minX, boundingBox.minX),
+- boundingBox1.minY,
+- Math.min(boundingBox1.minZ, boundingBox.minZ),
+- Math.max(boundingBox1.maxX, boundingBox.maxX),
+- boundingBox1.maxY,
+- Math.max(boundingBox1.maxZ, boundingBox.maxZ)
+- );
++ Entity entity = this.getVehicle();
++ AABB axisalignedbb;
++
++ if (entity != null) {
++ AABB axisalignedbb1 = entity.getBoundingBox();
++ AABB axisalignedbb2 = this.getBoundingBox();
++
++ axisalignedbb = new AABB(Math.min(axisalignedbb2.minX, axisalignedbb1.minX), axisalignedbb2.minY, Math.min(axisalignedbb2.minZ, axisalignedbb1.minZ), Math.max(axisalignedbb2.maxX, axisalignedbb1.maxX), axisalignedbb2.maxY, Math.max(axisalignedbb2.maxZ, axisalignedbb1.maxZ));
+ } else {
+- aABB = this.getBoundingBox();
++ axisalignedbb = this.getBoundingBox();
+ }
+
+- return aABB.inflate(DEFAULT_ATTACK_REACH, 0.0, DEFAULT_ATTACK_REACH);
++ return axisalignedbb.inflate(Mob.DEFAULT_ATTACK_REACH, 0.0D, Mob.DEFAULT_ATTACK_REACH);
+ }
+
+ @Override
+ public boolean doHurtTarget(Entity entity) {
+- float f = (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE);
+- float f1 = (float)this.getAttributeValue(Attributes.ATTACK_KNOCKBACK);
++ float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE);
++ float f1 = (float) this.getAttributeValue(Attributes.ATTACK_KNOCKBACK);
++
+ if (entity instanceof LivingEntity) {
+- f += EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity)entity).getMobType());
+- f1 += (float)EnchantmentHelper.getKnockbackBonus(this);
++ f += EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity) entity).getMobType());
++ f1 += (float) EnchantmentHelper.getKnockbackBonus(this);
+ }
+
+- int fireAspect = EnchantmentHelper.getFireAspect(this);
+- if (fireAspect > 0) {
+- entity.setSecondsOnFire(fireAspect * 4);
++ int i = EnchantmentHelper.getFireAspect(this);
++
++ if (i > 0) {
++ // 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.setSecondsOnFire(combustEvent.getDuration(), false);
++ }
++ // CraftBukkit end
+ }
+
+ boolean flag = entity.hurt(this.damageSources().mobAttack(this), f);
++
+ if (flag) {
+ if (f1 > 0.0F && entity instanceof LivingEntity) {
+- ((LivingEntity)entity)
+- .knockback(
+- (double)(f1 * 0.5F),
+- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)),
+- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)))
+- );
+- this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6));
++ ((LivingEntity) entity).knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)));
++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
+ }
+
+- if (entity instanceof Player player) {
+- this.maybeDisableShield(player, this.getMainHandItem(), player.isUsingItem() ? player.getUseItem() : ItemStack.EMPTY);
++ if (entity instanceof Player) {
++ Player entityhuman = (Player) entity;
++
++ this.maybeDisableShield(entityhuman, this.getMainHandItem(), entityhuman.isUsingItem() ? entityhuman.getUseItem() : ItemStack.EMPTY);
+ }
+
+ this.doEnchantDamageEffects(this, entity);
+@@ -1405,23 +1650,23 @@
+
+ private void maybeDisableShield(Player player, ItemStack mobItemStack, ItemStack playerItemStack) {
+ if (!mobItemStack.isEmpty() && !playerItemStack.isEmpty() && mobItemStack.getItem() instanceof AxeItem && playerItemStack.is(Items.SHIELD)) {
+- float f = 0.25F + (float)EnchantmentHelper.getBlockEfficiency(this) * 0.05F;
++ float f = 0.25F + (float) EnchantmentHelper.getBlockEfficiency(this) * 0.05F;
++
+ if (this.random.nextFloat() < f) {
+ player.getCooldowns().addCooldown(Items.SHIELD, 100);
+- this.level().broadcastEntityEvent(player, (byte)30);
++ this.level().broadcastEntityEvent(player, (byte) 30);
+ }
+ }
++
+ }
+
+ protected boolean isSunBurnTick() {
+ if (this.level().isDay() && !this.level().isClientSide) {
+- float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue();
+- BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ());
++ float f = this.getLightLevelDependentMagicValue();
++ BlockPos blockposition = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ());
+ boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow;
+- if (lightLevelDependentMagicValue > 0.5F
+- && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F
+- && !flag
+- && this.level().canSeeSky(blockPos)) {
++
++ if (f > 0.5F && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && !flag && this.level().canSeeSky(blockposition)) {
+ return true;
+ }
+ }
+@@ -1434,13 +1679,16 @@
+ if (this.getNavigation().canFloat()) {
+ super.jumpInLiquid(fluidTag);
+ } else {
+- this.setDeltaMovement(this.getDeltaMovement().add(0.0, 0.3, 0.0));
++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.3D, 0.0D));
+ }
++
+ }
+
+ @VisibleForTesting
+ public void removeFreeWill() {
+- this.removeAllGoals(goal -> true);
++ this.removeAllGoals((pathfindergoal) -> {
++ return true;
++ });
+ this.getBrain().removeAllBehaviors();
+ }
+
+@@ -1451,18 +1699,21 @@
+ @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(slot -> {
+- if (!slot.isEmpty()) {
+- slot.setCount(0);
++ this.getAllSlots().forEach((itemstack) -> {
++ if (!itemstack.isEmpty()) {
++ itemstack.setCount(0);
+ }
++
+ });
+ }
+
+ @Nullable
+ @Override
+ public ItemStack getPickResult() {
+- SpawnEggItem spawnEggItem = SpawnEggItem.byId(this.getType());
+- return spawnEggItem == null ? null : new ItemStack(spawnEggItem);
++ SpawnEggItem itemmonsteregg = SpawnEggItem.byId(this.getType());
++
++ return itemmonsteregg == null ? null : new ItemStack(itemmonsteregg);
+ }
+ }