--- a/net/minecraft/world/entity/animal/Fox.java
+++ b/net/minecraft/world/entity/animal/Fox.java
@@ -2,6 +2,7 @@
 
 import com.google.common.collect.Lists;
 import java.util.EnumSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
@@ -90,6 +91,7 @@
 import net.minecraft.world.phys.Vec3;
 
 public class Fox extends Animal implements VariantHolder<Fox.Type> {
+
     private static final EntityDataAccessor<Integer> DATA_TYPE_ID = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.INT);
     private static final EntityDataAccessor<Byte> DATA_FLAGS_ID = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.BYTE);
     private static final int FLAG_SITTING = 1;
@@ -101,14 +103,16 @@
     private static final int FLAG_DEFENDING = 128;
     public static final EntityDataAccessor<Optional<UUID>> DATA_TRUSTED_ID_0 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID);
     public static final EntityDataAccessor<Optional<UUID>> DATA_TRUSTED_ID_1 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID);
-    static final Predicate<ItemEntity> ALLOWED_ITEMS = (item) -> {
-        return !item.hasPickUpDelay() && item.isAlive();
+    static final Predicate<ItemEntity> ALLOWED_ITEMS = (entityitem) -> {
+        return !entityitem.hasPickUpDelay() && entityitem.isAlive();
     };
     private static final Predicate<Entity> TRUSTED_TARGET_SELECTOR = (entity) -> {
-        if (!(entity instanceof LivingEntity livingEntity)) {
+        if (!(entity instanceof LivingEntity)) {
             return false;
         } else {
-            return livingEntity.getLastHurtMob() != null && livingEntity.getLastHurtMobTimestamp() < livingEntity.tickCount + 600;
+            LivingEntity entityliving = (LivingEntity) entity;
+
+            return entityliving.getLastHurtMob() != null && entityliving.getLastHurtMobTimestamp() < entityliving.tickCount + 600;
         }
     };
     static final Predicate<Entity> STALKABLE_PREY = (entity) -> {
@@ -139,50 +143,50 @@
     @Override
     protected void defineSynchedData() {
         super.defineSynchedData();
-        this.entityData.define(DATA_TRUSTED_ID_0, Optional.empty());
-        this.entityData.define(DATA_TRUSTED_ID_1, Optional.empty());
-        this.entityData.define(DATA_TYPE_ID, 0);
-        this.entityData.define(DATA_FLAGS_ID, (byte)0);
+        this.entityData.define(Fox.DATA_TRUSTED_ID_0, Optional.empty());
+        this.entityData.define(Fox.DATA_TRUSTED_ID_1, Optional.empty());
+        this.entityData.define(Fox.DATA_TYPE_ID, 0);
+        this.entityData.define(Fox.DATA_FLAGS_ID, (byte) 0);
     }
 
     @Override
     protected void registerGoals() {
-        this.landTargetGoal = new NearestAttackableTargetGoal<>(this, Animal.class, 10, false, false, (entity) -> {
-            return entity instanceof Chicken || entity instanceof Rabbit;
+        this.landTargetGoal = new NearestAttackableTargetGoal<>(this, Animal.class, 10, false, false, (entityliving) -> {
+            return entityliving instanceof Chicken || entityliving instanceof Rabbit;
         });
         this.turtleEggTargetGoal = new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR);
-        this.fishTargetGoal = new NearestAttackableTargetGoal<>(this, AbstractFish.class, 20, false, false, (entity) -> {
-            return entity instanceof AbstractSchoolingFish;
+        this.fishTargetGoal = new NearestAttackableTargetGoal<>(this, AbstractFish.class, 20, false, false, (entityliving) -> {
+            return entityliving instanceof AbstractSchoolingFish;
         });
         this.goalSelector.addGoal(0, new Fox.FoxFloatGoal());
         this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level));
         this.goalSelector.addGoal(1, new Fox.FaceplantGoal());
         this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2D));
         this.goalSelector.addGoal(3, new Fox.FoxBreedGoal(1.0D));
-        this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Player.class, 16.0F, 1.6D, 1.4D, (entity) -> {
-            return AVOID_PLAYERS.test(entity) && !this.trusts(entity.getUUID()) && !this.isDefending();
+        this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Player.class, 16.0F, 1.6D, 1.4D, (entityliving) -> {
+            return Fox.AVOID_PLAYERS.test(entityliving) && !this.trusts(entityliving.getUUID()) && !this.isDefending();
         }));
-        this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Wolf.class, 8.0F, 1.6D, 1.4D, (entity) -> {
-            return !((Wolf)entity).isTame() && !this.isDefending();
+        this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Wolf.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
+            return !((Wolf) entityliving).isTame() && !this.isDefending();
         }));
-        this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, PolarBear.class, 8.0F, 1.6D, 1.4D, (entity) -> {
+        this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, PolarBear.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
             return !this.isDefending();
         }));
         this.goalSelector.addGoal(5, new Fox.StalkPreyGoal());
         this.goalSelector.addGoal(6, new Fox.FoxPounceGoal());
         this.goalSelector.addGoal(6, new Fox.SeekShelterGoal(1.25D));
-        this.goalSelector.addGoal(7, new Fox.FoxMeleeAttackGoal((double)1.2F, true));
+        this.goalSelector.addGoal(7, new Fox.FoxMeleeAttackGoal(1.2000000476837158D, true));
         this.goalSelector.addGoal(7, new Fox.SleepGoal());
         this.goalSelector.addGoal(8, new Fox.FoxFollowParentGoal(this, 1.25D));
         this.goalSelector.addGoal(9, new Fox.FoxStrollThroughVillageGoal(32, 200));
-        this.goalSelector.addGoal(10, new Fox.FoxEatBerriesGoal((double)1.2F, 12, 1));
+        this.goalSelector.addGoal(10, new Fox.FoxEatBerriesGoal(1.2000000476837158D, 12, 1));
         this.goalSelector.addGoal(10, new LeapAtTargetGoal(this, 0.4F));
         this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 1.0D));
         this.goalSelector.addGoal(11, new Fox.FoxSearchForItemsGoal());
         this.goalSelector.addGoal(12, new Fox.FoxLookAtPlayerGoal(this, Player.class, 24.0F));
         this.goalSelector.addGoal(13, new Fox.PerchAndSearchGoal());
-        this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entity) -> {
-            return TRUSTED_TARGET_SELECTOR.test(entity) && !this.trusts(entity.getUUID());
+        this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving) -> {
+            return Fox.TRUSTED_TARGET_SELECTOR.test(entityliving) && !this.trusts(entityliving.getUUID());
         }));
     }
 
@@ -195,23 +199,26 @@
     public void aiStep() {
         if (!this.level.isClientSide && this.isAlive() && this.isEffectiveAi()) {
             ++this.ticksSinceEaten;
-            ItemStack itemStack = this.getItemBySlot(EquipmentSlot.MAINHAND);
-            if (this.canEat(itemStack)) {
+            ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND);
+
+            if (this.canEat(itemstack)) {
                 if (this.ticksSinceEaten > 600) {
-                    ItemStack itemStack2 = itemStack.finishUsingItem(this.level, this);
-                    if (!itemStack2.isEmpty()) {
-                        this.setItemSlot(EquipmentSlot.MAINHAND, itemStack2);
+                    ItemStack itemstack1 = itemstack.finishUsingItem(this.level, this);
+
+                    if (!itemstack1.isEmpty()) {
+                        this.setItemSlot(EquipmentSlot.MAINHAND, itemstack1);
                     }
 
                     this.ticksSinceEaten = 0;
                 } else if (this.ticksSinceEaten > 560 && this.random.nextFloat() < 0.1F) {
-                    this.playSound(this.getEatingSound(itemStack), 1.0F, 1.0F);
-                    this.level.broadcastEntityEvent(this, (byte)45);
+                    this.playSound(this.getEatingSound(itemstack), 1.0F, 1.0F);
+                    this.level.broadcastEntityEvent(this, (byte) 45);
                 }
             }
 
-            LivingEntity livingEntity = this.getTarget();
-            if (livingEntity == null || !livingEntity.isAlive()) {
+            LivingEntity entityliving = this.getTarget();
+
+            if (entityliving == null || !entityliving.isAlive()) {
                 this.setIsCrouching(false);
                 this.setIsInterested(false);
             }
@@ -243,22 +250,23 @@
     protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance localDifficulty) {
         if (random.nextFloat() < 0.2F) {
             float f = random.nextFloat();
-            ItemStack itemStack;
+            ItemStack itemstack;
+
             if (f < 0.05F) {
-                itemStack = new ItemStack(Items.EMERALD);
+                itemstack = new ItemStack(Items.EMERALD);
             } else if (f < 0.2F) {
-                itemStack = new ItemStack(Items.EGG);
+                itemstack = new ItemStack(Items.EGG);
             } else if (f < 0.4F) {
-                itemStack = random.nextBoolean() ? new ItemStack(Items.RABBIT_FOOT) : new ItemStack(Items.RABBIT_HIDE);
+                itemstack = random.nextBoolean() ? new ItemStack(Items.RABBIT_FOOT) : new ItemStack(Items.RABBIT_HIDE);
             } else if (f < 0.6F) {
-                itemStack = new ItemStack(Items.WHEAT);
+                itemstack = new ItemStack(Items.WHEAT);
             } else if (f < 0.8F) {
-                itemStack = new ItemStack(Items.LEATHER);
+                itemstack = new ItemStack(Items.LEATHER);
             } else {
-                itemStack = new ItemStack(Items.FEATHER);
+                itemstack = new ItemStack(Items.FEATHER);
             }
 
-            this.setItemSlot(EquipmentSlot.MAINHAND, itemStack);
+            this.setItemSlot(EquipmentSlot.MAINHAND, itemstack);
         }
 
     }
@@ -266,11 +274,13 @@
     @Override
     public void handleEntityEvent(byte status) {
         if (status == 45) {
-            ItemStack itemStack = this.getItemBySlot(EquipmentSlot.MAINHAND);
-            if (!itemStack.isEmpty()) {
-                for(int i = 0; i < 8; ++i) {
-                    Vec3 vec3 = (new Vec3(((double)this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D)).xRot(-this.getXRot() * ((float)Math.PI / 180F)).yRot(-this.getYRot() * ((float)Math.PI / 180F));
-                    this.level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, itemStack), this.getX() + this.getLookAngle().x / 2.0D, this.getY(), this.getZ() + this.getLookAngle().z / 2.0D, vec3.x, vec3.y + 0.05D, vec3.z);
+            ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND);
+
+            if (!itemstack.isEmpty()) {
+                for (int i = 0; i < 8; ++i) {
+                    Vec3 vec3d = (new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D)).xRot(-this.getXRot() * 0.017453292F).yRot(-this.getYRot() * 0.017453292F);
+
+                    this.level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, itemstack), this.getX() + this.getLookAngle().x / 2.0D, this.getY(), this.getZ() + this.getLookAngle().z / 2.0D, vec3d.x, vec3d.y + 0.05D, vec3d.z);
                 }
             }
         } else {
@@ -280,18 +290,19 @@
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, (double)0.3F).add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 32.0D).add(Attributes.ATTACK_DAMAGE, 2.0D);
+        return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 32.0D).add(Attributes.ATTACK_DAMAGE, 2.0D);
     }
 
     @Nullable
     @Override
-    public Fox getBreedOffspring(ServerLevel serverLevel, AgeableMob ageableMob) {
-        Fox fox = EntityType.FOX.create(serverLevel);
-        if (fox != null) {
-            fox.setVariant(this.random.nextBoolean() ? this.getVariant() : ((Fox)ageableMob).getVariant());
+    public Fox getBreedOffspring(ServerLevel world, AgeableMob entity) {
+        Fox entityfox = (Fox) EntityType.FOX.create(world);
+
+        if (entityfox != null) {
+            entityfox.setVariant(this.random.nextBoolean() ? this.getVariant() : ((Fox) entity).getVariant());
         }
 
-        return fox;
+        return entityfox;
     }
 
     public static boolean checkFoxSpawnRules(EntityType<Fox> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
@@ -302,19 +313,22 @@
     @Override
     public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) {
         Holder<Biome> holder = world.getBiome(this.blockPosition());
-        Fox.Type type = Fox.Type.byBiome(holder);
-        boolean bl = false;
-        if (entityData instanceof Fox.FoxGroupData foxGroupData) {
-            type = foxGroupData.type;
-            if (foxGroupData.getGroupSize() >= 2) {
-                bl = true;
+        Fox.Type entityfox_type = Fox.Type.byBiome(holder);
+        boolean flag = false;
+
+        if (entityData instanceof Fox.FoxGroupData) {
+            Fox.FoxGroupData entityfox_i = (Fox.FoxGroupData) entityData;
+
+            entityfox_type = entityfox_i.type;
+            if (entityfox_i.getGroupSize() >= 2) {
+                flag = true;
             }
         } else {
-            entityData = new Fox.FoxGroupData(type);
+            entityData = new Fox.FoxGroupData(entityfox_type);
         }
 
-        this.setVariant(type);
-        if (bl) {
+        this.setVariant(entityfox_type);
+        if (flag) {
             this.setAge(-24000);
         }
 
@@ -323,7 +337,7 @@
         }
 
         this.populateDefaultEquipmentSlots(world.getRandom(), difficulty);
-        return super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt);
+        return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityNbt);
     }
 
     private void setTargetGoals() {
@@ -355,26 +369,26 @@
 
     @Override
     public Fox.Type getVariant() {
-        return Fox.Type.byId(this.entityData.get(DATA_TYPE_ID));
+        return Fox.Type.byId((Integer) this.entityData.get(Fox.DATA_TYPE_ID));
     }
 
-    @Override
     public void setVariant(Fox.Type variant) {
-        this.entityData.set(DATA_TYPE_ID, variant.getId());
+        this.entityData.set(Fox.DATA_TYPE_ID, variant.getId());
     }
 
     List<UUID> getTrustedUUIDs() {
         List<UUID> list = Lists.newArrayList();
-        list.add(this.entityData.get(DATA_TRUSTED_ID_0).orElse((UUID)null));
-        list.add(this.entityData.get(DATA_TRUSTED_ID_1).orElse((UUID)null));
+
+        list.add((UUID) ((Optional) this.entityData.get(Fox.DATA_TRUSTED_ID_0)).orElse((Object) null));
+        list.add((UUID) ((Optional) this.entityData.get(Fox.DATA_TRUSTED_ID_1)).orElse((Object) null));
         return list;
     }
 
     void addTrustedUUID(@Nullable UUID uuid) {
-        if (this.entityData.get(DATA_TRUSTED_ID_0).isPresent()) {
-            this.entityData.set(DATA_TRUSTED_ID_1, Optional.ofNullable(uuid));
+        if (((Optional) this.entityData.get(Fox.DATA_TRUSTED_ID_0)).isPresent()) {
+            this.entityData.set(Fox.DATA_TRUSTED_ID_1, Optional.ofNullable(uuid));
         } else {
-            this.entityData.set(DATA_TRUSTED_ID_0, Optional.ofNullable(uuid));
+            this.entityData.set(Fox.DATA_TRUSTED_ID_0, Optional.ofNullable(uuid));
         }
 
     }
@@ -383,15 +397,18 @@
     public void addAdditionalSaveData(CompoundTag nbt) {
         super.addAdditionalSaveData(nbt);
         List<UUID> list = this.getTrustedUUIDs();
-        ListTag listTag = new ListTag();
+        ListTag nbttaglist = new ListTag();
+        Iterator iterator = list.iterator();
 
-        for(UUID uUID : list) {
-            if (uUID != null) {
-                listTag.add(NbtUtils.createUUID(uUID));
+        while (iterator.hasNext()) {
+            UUID uuid = (UUID) iterator.next();
+
+            if (uuid != null) {
+                nbttaglist.add(NbtUtils.createUUID(uuid));
             }
         }
 
-        nbt.put("Trusted", listTag);
+        nbt.put("Trusted", nbttaglist);
         nbt.putBoolean("Sleeping", this.isSleeping());
         nbt.putString("Type", this.getVariant().getSerializedName());
         nbt.putBoolean("Sitting", this.isSitting());
@@ -401,15 +418,15 @@
     @Override
     public void readAdditionalSaveData(CompoundTag nbt) {
         super.readAdditionalSaveData(nbt);
-        ListTag listTag = nbt.getList("Trusted", 11);
+        ListTag nbttaglist = nbt.getList("Trusted", 11);
 
-        for(int i = 0; i < listTag.size(); ++i) {
-            this.addTrustedUUID(NbtUtils.loadUUID(listTag.get(i)));
+        for (int i = 0; i < nbttaglist.size(); ++i) {
+            this.addTrustedUUID(NbtUtils.loadUUID(nbttaglist.get(i)));
         }
 
         this.setSleeping(nbt.getBoolean("Sleeping"));
         this.setVariant(Fox.Type.byName(nbt.getString("Type")));
-        this.setSitting(nbt.getBoolean("Sitting"));
+        this.setSitting(nbt.getBoolean("Sitting"), false); // Paper
         this.setIsCrouching(nbt.getBoolean("Crouching"));
         if (this.level instanceof ServerLevel) {
             this.setTargetGoals();
@@ -422,6 +439,12 @@
     }
 
     public void setSitting(boolean sitting) {
+        this.setSitting(sitting, true);
+    }
+    // Paper start
+    public void setSitting(boolean sitting, boolean fireEvent) {
+        if (fireEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return;
+    // Paper end
         this.setFlag(1, sitting);
     }
 
@@ -452,63 +475,66 @@
 
     private void setFlag(int mask, boolean value) {
         if (value) {
-            this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) | mask));
+            this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) | mask));
         } else {
-            this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) & ~mask));
+            this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & ~mask));
         }
 
     }
 
     private boolean getFlag(int bitmask) {
-        return (this.entityData.get(DATA_FLAGS_ID) & bitmask) != 0;
+        return ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & bitmask) != 0;
     }
 
     @Override
     public boolean canTakeItem(ItemStack stack) {
-        EquipmentSlot equipmentSlot = Mob.getEquipmentSlotForItem(stack);
-        if (!this.getItemBySlot(equipmentSlot).isEmpty()) {
-            return false;
-        } else {
-            return equipmentSlot == EquipmentSlot.MAINHAND && super.canTakeItem(stack);
-        }
+        EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(stack);
+
+        return !this.getItemBySlot(enumitemslot).isEmpty() ? false : enumitemslot == EquipmentSlot.MAINHAND && super.canTakeItem(stack);
     }
 
     @Override
     public boolean canHoldItem(ItemStack stack) {
         Item item = stack.getItem();
-        ItemStack itemStack = this.getItemBySlot(EquipmentSlot.MAINHAND);
-        return itemStack.isEmpty() || this.ticksSinceEaten > 0 && item.isEdible() && !itemStack.getItem().isEdible();
+        ItemStack itemstack1 = this.getItemBySlot(EquipmentSlot.MAINHAND);
+
+        return itemstack1.isEmpty() || this.ticksSinceEaten > 0 && item.isEdible() && !itemstack1.getItem().isEdible();
     }
 
     private void spitOutItem(ItemStack stack) {
         if (!stack.isEmpty() && !this.level.isClientSide) {
-            ItemEntity itemEntity = new ItemEntity(this.level, this.getX() + this.getLookAngle().x, this.getY() + 1.0D, this.getZ() + this.getLookAngle().z, stack);
-            itemEntity.setPickUpDelay(40);
-            itemEntity.setThrower(this.getUUID());
+            ItemEntity entityitem = new ItemEntity(this.level, this.getX() + this.getLookAngle().x, this.getY() + 1.0D, this.getZ() + this.getLookAngle().z, stack);
+
+            entityitem.setPickUpDelay(40);
+            entityitem.setThrower(this.getUUID());
             this.playSound(SoundEvents.FOX_SPIT, 1.0F, 1.0F);
-            this.level.addFreshEntity(itemEntity);
+            this.spawnAtLocation(entityitem); // Paper - call EntityDropItemEvent
         }
     }
 
     private void dropItemStack(ItemStack stack) {
-        ItemEntity itemEntity = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), stack);
-        this.level.addFreshEntity(itemEntity);
+        ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), stack);
+
+        this.spawnAtLocation(entityitem); // Paper - call EntityDropItemEvent
     }
 
     @Override
     protected void pickUpItem(ItemEntity item) {
-        ItemStack itemStack = item.getItem();
-        if (this.canHoldItem(itemStack)) {
-            int i = itemStack.getCount();
+        ItemStack itemstack = item.getItem();
+
+        if (!org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callEntityPickupItemEvent(this, item, itemstack.getCount() - 1, !this.canHoldItem(itemstack)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent
+            itemstack = item.getItem(); // CraftBukkit - update ItemStack from event
+            int i = itemstack.getCount();
+
             if (i > 1) {
-                this.dropItemStack(itemStack.split(i - 1));
+                this.dropItemStack(itemstack.split(i - 1));
             }
 
             this.spitOutItem(this.getItemBySlot(EquipmentSlot.MAINHAND));
             this.onItemPickup(item);
-            this.setItemSlot(EquipmentSlot.MAINHAND, itemStack.split(1));
+            this.setItemSlot(EquipmentSlot.MAINHAND, itemstack.split(1));
             this.setGuaranteedDrop(EquipmentSlot.MAINHAND);
-            this.take(item, itemStack.getCount());
+            this.take(item, itemstack.getCount());
             item.discard();
             this.ticksSinceEaten = 0;
         }
@@ -519,19 +545,21 @@
     public void tick() {
         super.tick();
         if (this.isEffectiveAi()) {
-            boolean bl = this.isInWater();
-            if (bl || this.getTarget() != null || this.level.isThundering()) {
+            boolean flag = this.isInWater();
+
+            if (flag || this.getTarget() != null || this.level.isThundering()) {
                 this.wakeUp();
             }
 
-            if (bl || this.isSleeping()) {
+            if (flag || this.isSleeping()) {
                 this.setSitting(false);
             }
 
             if (this.isFaceplanted() && this.level.random.nextFloat() < 0.2F) {
-                BlockPos blockPos = this.blockPosition();
-                BlockState blockState = this.level.getBlockState(blockPos);
-                this.level.levelEvent(2001, blockPos, Block.getId(blockState));
+                BlockPos blockposition = this.blockPosition();
+                BlockState iblockdata = this.level.getBlockState(blockposition);
+
+                this.level.levelEvent(2001, blockposition, Block.getId(iblockdata));
             }
         }
 
@@ -561,7 +589,7 @@
 
     @Override
     protected void onOffspringSpawnedFromEgg(Player player, Mob child) {
-        ((Fox)child).addTrustedUUID(player.getUUID());
+        ((Fox) child).addTrustedUUID(player.getUUID());
     }
 
     public boolean isPouncing() {
@@ -598,7 +626,7 @@
     }
 
     public float getHeadRollAngle(float tickDelta) {
-        return Mth.lerp(tickDelta, this.interestedAngleO, this.interestedAngle) * 0.11F * (float)Math.PI;
+        return Mth.lerp(tickDelta, this.interestedAngleO, this.interestedAngle) * 0.11F * 3.1415927F;
     }
 
     public float getCrouchAmount(float tickDelta) {
@@ -638,9 +666,10 @@
 
     @Override
     public void playAmbientSound() {
-        SoundEvent soundEvent = this.getAmbientSound();
-        if (soundEvent == SoundEvents.FOX_SCREECH) {
-            this.playSound(soundEvent, 2.0F, this.getVoicePitch());
+        SoundEvent soundeffect = this.getAmbientSound();
+
+        if (soundeffect == SoundEvents.FOX_SCREECH) {
+            this.playSound(soundeffect, 2.0F, this.getVoicePitch());
         } else {
             super.playAmbientSound();
         }
@@ -655,6 +684,7 @@
         } else {
             if (!this.level.isDay() && this.random.nextFloat() < 0.1F) {
                 List<Player> list = this.level.getEntitiesOfClass(Player.class, this.getBoundingBox().inflate(16.0D, 16.0D, 16.0D), EntitySelector.NO_SPECTATORS);
+
                 if (list.isEmpty()) {
                     return SoundEvents.FOX_SCREECH;
                 }
@@ -681,28 +711,39 @@
     }
 
     @Override
-    protected void dropAllDeathLoot(DamageSource source) {
-        ItemStack itemStack = this.getItemBySlot(EquipmentSlot.MAINHAND);
-        if (!itemStack.isEmpty()) {
-            this.spawnAtLocation(itemStack);
+    // Paper start - Cancellable death event
+    protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) {
+        ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper - modified by supercall
+
+        org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(source);
+
+        // Below is code to drop
+
+        if (deathEvent == null || deathEvent.isCancelled()) {
+            return deathEvent;
+        }
+        // Paper end
+
+        if (!itemstack.isEmpty()) {
+            this.spawnAtLocation(itemstack);
             this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
         }
 
-        super.dropAllDeathLoot(source);
+        return deathEvent; // Paper
     }
 
     public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) {
-        double d = chasedEntity.getZ() - fox.getZ();
-        double e = chasedEntity.getX() - fox.getX();
-        double f = d / e;
-        int i = 6;
+        double d0 = chasedEntity.getZ() - fox.getZ();
+        double d1 = chasedEntity.getX() - fox.getX();
+        double d2 = d0 / d1;
+        boolean flag = true;
 
-        for(int j = 0; j < 6; ++j) {
-            double g = f == 0.0D ? 0.0D : d * (double)((float)j / 6.0F);
-            double h = f == 0.0D ? e * (double)((float)j / 6.0F) : g / f;
+        for (int i = 0; i < 6; ++i) {
+            double d3 = d2 == 0.0D ? 0.0D : d0 * (double) ((float) i / 6.0F);
+            double d4 = d2 == 0.0D ? d1 * (double) ((float) i / 6.0F) : d3 / d2;
 
-            for(int k = 1; k < 4; ++k) {
-                if (!fox.level.getBlockState(new BlockPos(fox.getX() + h, fox.getY() + (double)k, fox.getZ() + g)).canBeReplaced()) {
+            for (int j = 1; j < 4; ++j) {
+                if (!fox.level.getBlockState(new BlockPos(fox.getX() + d4, fox.getY() + (double) j, fox.getZ() + d3)).canBeReplaced()) {
                     return false;
                 }
             }
@@ -713,58 +754,64 @@
 
     @Override
     public Vec3 getLeashOffset() {
-        return new Vec3(0.0D, (double)(0.55F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F));
+        return new Vec3(0.0D, (double) (0.55F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F));
     }
 
-    class DefendTrustedTargetGoal extends NearestAttackableTargetGoal<LivingEntity> {
-        @Nullable
-        private LivingEntity trustedLastHurtBy;
-        @Nullable
-        private LivingEntity trustedLastHurt;
-        private int timestamp;
+    public class FoxLookControl extends LookControl {
 
-        public DefendTrustedTargetGoal(Class<LivingEntity> targetEntityClass, boolean checkVisibility, boolean checkCanNavigate, @Nullable Predicate<LivingEntity> targetPredicate) {
-            super(Fox.this, targetEntityClass, 10, checkVisibility, checkCanNavigate, targetPredicate);
+        public FoxLookControl() {
+            super(Fox.this);
         }
 
         @Override
-        public boolean canUse() {
-            if (this.randomInterval > 0 && this.mob.getRandom().nextInt(this.randomInterval) != 0) {
-                return false;
-            } else {
-                for(UUID uUID : Fox.this.getTrustedUUIDs()) {
-                    if (uUID != null && Fox.this.level instanceof ServerLevel) {
-                        Entity entity = ((ServerLevel)Fox.this.level).getEntity(uUID);
-                        if (entity instanceof LivingEntity) {
-                            LivingEntity livingEntity = (LivingEntity)entity;
-                            this.trustedLastHurt = livingEntity;
-                            this.trustedLastHurtBy = livingEntity.getLastHurtByMob();
-                            int i = livingEntity.getLastHurtByMobTimestamp();
-                            return i != this.timestamp && this.canAttack(this.trustedLastHurtBy, this.targetConditions);
-                        }
-                    }
-                }
-
-                return false;
+        public void tick() {
+            if (!Fox.this.isSleeping()) {
+                super.tick();
             }
+
         }
 
         @Override
-        public void start() {
-            this.setTarget(this.trustedLastHurtBy);
-            this.target = this.trustedLastHurtBy;
-            if (this.trustedLastHurt != null) {
-                this.timestamp = this.trustedLastHurt.getLastHurtByMobTimestamp();
+        protected boolean resetXRotOnTick() {
+            return !Fox.this.isPouncing() && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.isFaceplanted();
+        }
+    }
+
+    private class FoxMoveControl extends MoveControl {
+
+        public FoxMoveControl() {
+            super(Fox.this);
+        }
+
+        @Override
+        public void tick() {
+            if (Fox.this.canMove()) {
+                super.tick();
             }
 
-            Fox.this.playSound(SoundEvents.FOX_AGGRO, 1.0F, 1.0F);
-            Fox.this.setDefending(true);
-            Fox.this.wakeUp();
+        }
+    }
+
+    private class FoxFloatGoal extends FloatGoal {
+
+        public FoxFloatGoal() {
+            super(Fox.this);
+        }
+
+        @Override
+        public void start() {
             super.start();
+            Fox.this.clearStates();
+        }
+
+        @Override
+        public boolean canUse() {
+            return Fox.this.isInWater() && Fox.this.getFluidHeight(FluidTags.WATER) > 0.25D || Fox.this.isInLava();
         }
     }
 
-    class FaceplantGoal extends Goal {
+    private class FaceplantGoal extends Goal {
+
         int countdown;
 
         public FaceplantGoal() {
@@ -797,414 +844,511 @@
         }
     }
 
-    public class FoxAlertableEntitiesSelector implements Predicate<LivingEntity> {
-        @Override
-        public boolean test(LivingEntity livingEntity) {
-            if (livingEntity instanceof Fox) {
-                return false;
-            } else if (!(livingEntity instanceof Chicken) && !(livingEntity instanceof Rabbit) && !(livingEntity instanceof Monster)) {
-                if (livingEntity instanceof TamableAnimal) {
-                    return !((TamableAnimal)livingEntity).isTame();
-                } else if (!(livingEntity instanceof Player) || !livingEntity.isSpectator() && !((Player)livingEntity).isCreative()) {
-                    if (Fox.this.trusts(livingEntity.getUUID())) {
-                        return false;
-                    } else {
-                        return !livingEntity.isSleeping() && !livingEntity.isDiscrete();
-                    }
-                } else {
-                    return false;
-                }
-            } else {
-                return true;
-            }
-        }
-    }
-
-    abstract class FoxBehaviorGoal extends Goal {
-        private final TargetingConditions alertableTargeting = TargetingConditions.forCombat().range(12.0D).ignoreLineOfSight().selector(Fox.this.new FoxAlertableEntitiesSelector());
+    private class FoxPanicGoal extends PanicGoal {
 
-        protected boolean hasShelter() {
-            BlockPos blockPos = new BlockPos(Fox.this.getX(), Fox.this.getBoundingBox().maxY, Fox.this.getZ());
-            return !Fox.this.level.canSeeSky(blockPos) && Fox.this.getWalkTargetValue(blockPos) >= 0.0F;
+        public FoxPanicGoal(double d0) {
+            super(Fox.this, d0);
         }
 
-        protected boolean alertable() {
-            return !Fox.this.level.getNearbyEntities(LivingEntity.class, this.alertableTargeting, Fox.this, Fox.this.getBoundingBox().inflate(12.0D, 6.0D, 12.0D)).isEmpty();
+        @Override
+        public boolean shouldPanic() {
+            return !Fox.this.isDefending() && super.shouldPanic();
         }
     }
 
-    class FoxBreedGoal extends BreedGoal {
-        public FoxBreedGoal(double chance) {
-            super(Fox.this, chance);
+    private class FoxBreedGoal extends BreedGoal {
+
+        public FoxBreedGoal(double d0) {
+            super(Fox.this, d0);
         }
 
         @Override
         public void start() {
-            ((Fox)this.animal).clearStates();
-            ((Fox)this.partner).clearStates();
+            ((Fox) this.animal).clearStates();
+            ((Fox) this.partner).clearStates();
             super.start();
         }
 
         @Override
         protected void breed() {
-            ServerLevel serverLevel = (ServerLevel)this.level;
-            Fox fox = (Fox)this.animal.getBreedOffspring(serverLevel, this.partner);
-            if (fox != null) {
-                ServerPlayer serverPlayer = this.animal.getLoveCause();
-                ServerPlayer serverPlayer2 = this.partner.getLoveCause();
-                ServerPlayer serverPlayer3 = serverPlayer;
-                if (serverPlayer != null) {
-                    fox.addTrustedUUID(serverPlayer.getUUID());
+            ServerLevel worldserver = (ServerLevel) this.level;
+            Fox entityfox = (Fox) this.animal.getBreedOffspring(worldserver, this.partner);
+
+            if (entityfox != null) {
+                ServerPlayer entityplayer = this.animal.getLoveCause();
+                ServerPlayer entityplayer1 = this.partner.getLoveCause();
+                ServerPlayer entityplayer2 = entityplayer;
+
+                if (entityplayer != null) {
+                    entityfox.addTrustedUUID(entityplayer.getUUID());
                 } else {
-                    serverPlayer3 = serverPlayer2;
+                    entityplayer2 = entityplayer1;
                 }
 
-                if (serverPlayer2 != null && serverPlayer != serverPlayer2) {
-                    fox.addTrustedUUID(serverPlayer2.getUUID());
+                if (entityplayer1 != null && entityplayer != entityplayer1) {
+                    entityfox.addTrustedUUID(entityplayer1.getUUID());
                 }
+                // CraftBukkit start - call EntityBreedEvent
+                entityfox.setAge(-24000);
+                entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
+                int experience = this.animal.getRandom().nextInt(7) + 1;
+                org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callEntityBreedEvent(entityfox, animal, partner, entityplayer, this.animal.breedItem, experience);
+                if (entityBreedEvent.isCancelled()) {
+                    return;
+                }
+                experience = entityBreedEvent.getExperience();
+                // CraftBukkit end
 
-                if (serverPlayer3 != null) {
-                    serverPlayer3.awardStat(Stats.ANIMALS_BRED);
-                    CriteriaTriggers.BRED_ANIMALS.trigger(serverPlayer3, this.animal, this.partner, fox);
+                if (entityplayer2 != null) {
+                    entityplayer2.awardStat(Stats.ANIMALS_BRED);
+                    CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer2, this.animal, this.partner, entityfox);
                 }
 
                 this.animal.setAge(6000);
                 this.partner.setAge(6000);
                 this.animal.resetLove();
                 this.partner.resetLove();
-                fox.setAge(-24000);
-                fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
-                serverLevel.addFreshEntityWithPassengers(fox);
-                this.level.broadcastEntityEvent(this.animal, (byte)18);
+                worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason
+                this.level.broadcastEntityEvent(this.animal, (byte) 18);
                 if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
-                    this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1));
+                    // CraftBukkit start - use event experience
+                    if (experience > 0) {
+                        this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper
+                    }
+                    // CraftBukkit end
                 }
 
             }
         }
     }
 
-    public class FoxEatBerriesGoal extends MoveToBlockGoal {
-        private static final int WAIT_TICKS = 40;
-        protected int ticksWaited;
+    private class StalkPreyGoal extends Goal {
 
-        public FoxEatBerriesGoal(double speed, int range, int maxYDifference) {
-            super(Fox.this, speed, range, maxYDifference);
+        public StalkPreyGoal() {
+            this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
         }
 
         @Override
-        public double acceptedDistance() {
-            return 2.0D;
+        public boolean canUse() {
+            if (Fox.this.isSleeping()) {
+                return false;
+            } else {
+                LivingEntity entityliving = Fox.this.getTarget();
+
+                return entityliving != null && entityliving.isAlive() && Fox.STALKABLE_PREY.test(entityliving) && Fox.this.distanceToSqr((Entity) entityliving) > 36.0D && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.jumping;
+            }
         }
 
         @Override
-        public boolean shouldRecalculatePath() {
-            return this.tryTicks % 100 == 0;
+        public void start() {
+            Fox.this.setSitting(false);
+            Fox.this.setFaceplanted(false);
         }
 
         @Override
-        protected boolean isValidTarget(LevelReader world, BlockPos pos) {
-            BlockState blockState = world.getBlockState(pos);
-            return blockState.is(Blocks.SWEET_BERRY_BUSH) && blockState.getValue(SweetBerryBushBlock.AGE) >= 2 || CaveVines.hasGlowBerries(blockState);
+        public void stop() {
+            LivingEntity entityliving = Fox.this.getTarget();
+
+            if (entityliving != null && Fox.isPathClear(Fox.this, entityliving)) {
+                Fox.this.setIsInterested(true);
+                Fox.this.setIsCrouching(true);
+                Fox.this.getNavigation().stop();
+                Fox.this.getLookControl().setLookAt(entityliving, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot());
+            } else {
+                Fox.this.setIsInterested(false);
+                Fox.this.setIsCrouching(false);
+            }
+
         }
 
         @Override
         public void tick() {
-            if (this.isReachedTarget()) {
-                if (this.ticksWaited >= 40) {
-                    this.onReachedTarget();
+            LivingEntity entityliving = Fox.this.getTarget();
+
+            if (entityliving != null) {
+                Fox.this.getLookControl().setLookAt(entityliving, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot());
+                if (Fox.this.distanceToSqr((Entity) entityliving) <= 36.0D) {
+                    Fox.this.setIsInterested(true);
+                    Fox.this.setIsCrouching(true);
+                    Fox.this.getNavigation().stop();
                 } else {
-                    ++this.ticksWaited;
+                    Fox.this.getNavigation().moveTo((Entity) entityliving, 1.5D);
                 }
-            } else if (!this.isReachedTarget() && Fox.this.random.nextFloat() < 0.05F) {
-                Fox.this.playSound(SoundEvents.FOX_SNIFF, 1.0F, 1.0F);
-            }
 
-            super.tick();
+            }
         }
+    }
 
-        protected void onReachedTarget() {
-            if (Fox.this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
-                BlockState blockState = Fox.this.level.getBlockState(this.blockPos);
-                if (blockState.is(Blocks.SWEET_BERRY_BUSH)) {
-                    this.pickSweetBerries(blockState);
-                } else if (CaveVines.hasGlowBerries(blockState)) {
-                    this.pickGlowBerry(blockState);
-                }
+    public class FoxPounceGoal extends JumpGoal {
 
+        public FoxPounceGoal() {}
+
+        @Override
+        public boolean canUse() {
+            if (!Fox.this.isFullyCrouched()) {
+                return false;
+            } else {
+                LivingEntity entityliving = Fox.this.getTarget();
+
+                if (entityliving != null && entityliving.isAlive()) {
+                    if (entityliving.getMotionDirection() != entityliving.getDirection()) {
+                        return false;
+                    } else {
+                        boolean flag = Fox.isPathClear(Fox.this, entityliving);
+
+                        if (!flag) {
+                            Fox.this.getNavigation().createPath((Entity) entityliving, 0);
+                            Fox.this.setIsCrouching(false);
+                            Fox.this.setIsInterested(false);
+                        }
+
+                        return flag;
+                    }
+                } else {
+                    return false;
+                }
             }
         }
 
-        private void pickGlowBerry(BlockState state) {
-            CaveVines.use(state, Fox.this.level, this.blockPos);
-        }
+        @Override
+        public boolean canContinueToUse() {
+            LivingEntity entityliving = Fox.this.getTarget();
 
-        private void pickSweetBerries(BlockState state) {
-            int i = state.getValue(SweetBerryBushBlock.AGE);
-            state.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(1));
-            int j = 1 + Fox.this.level.random.nextInt(2) + (i == 3 ? 1 : 0);
-            ItemStack itemStack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND);
-            if (itemStack.isEmpty()) {
-                Fox.this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.SWEET_BERRIES));
-                --j;
-            }
+            if (entityliving != null && entityliving.isAlive()) {
+                double d0 = Fox.this.getDeltaMovement().y;
 
-            if (j > 0) {
-                Block.popResource(Fox.this.level, this.blockPos, new ItemStack(Items.SWEET_BERRIES, j));
+                return (d0 * d0 >= 0.05000000074505806D || Math.abs(Fox.this.getXRot()) >= 15.0F || !Fox.this.onGround) && !Fox.this.isFaceplanted();
+            } else {
+                return false;
             }
-
-            Fox.this.playSound(SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, 1.0F, 1.0F);
-            Fox.this.level.setBlock(this.blockPos, state.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(1)), 2);
         }
 
         @Override
-        public boolean canUse() {
-            return !Fox.this.isSleeping() && super.canUse();
+        public boolean isInterruptable() {
+            return false;
         }
 
         @Override
         public void start() {
-            this.ticksWaited = 0;
-            Fox.this.setSitting(false);
-            super.start();
-        }
-    }
+            Fox.this.setJumping(true);
+            Fox.this.setIsPouncing(true);
+            Fox.this.setIsInterested(false);
+            LivingEntity entityliving = Fox.this.getTarget();
 
-    class FoxFloatGoal extends FloatGoal {
-        public FoxFloatGoal() {
-            super(Fox.this);
+            if (entityliving != null) {
+                Fox.this.getLookControl().setLookAt(entityliving, 60.0F, 30.0F);
+                Vec3 vec3d = (new Vec3(entityliving.getX() - Fox.this.getX(), entityliving.getY() - Fox.this.getY(), entityliving.getZ() - Fox.this.getZ())).normalize();
+
+                Fox.this.setDeltaMovement(Fox.this.getDeltaMovement().add(vec3d.x * 0.8D, 0.9D, vec3d.z * 0.8D));
+            }
+
+            Fox.this.getNavigation().stop();
         }
 
         @Override
-        public void start() {
-            super.start();
-            Fox.this.clearStates();
+        public void stop() {
+            Fox.this.setIsCrouching(false);
+            Fox.this.crouchAmount = 0.0F;
+            Fox.this.crouchAmountO = 0.0F;
+            Fox.this.setIsInterested(false);
+            Fox.this.setIsPouncing(false);
         }
 
         @Override
-        public boolean canUse() {
-            return Fox.this.isInWater() && Fox.this.getFluidHeight(FluidTags.WATER) > 0.25D || Fox.this.isInLava();
+        public void tick() {
+            LivingEntity entityliving = Fox.this.getTarget();
+
+            if (entityliving != null) {
+                Fox.this.getLookControl().setLookAt(entityliving, 60.0F, 30.0F);
+            }
+
+            if (!Fox.this.isFaceplanted()) {
+                Vec3 vec3d = Fox.this.getDeltaMovement();
+
+                if (vec3d.y * vec3d.y < 0.029999999329447746D && Fox.this.getXRot() != 0.0F) {
+                    Fox.this.setXRot(Mth.rotlerp(Fox.this.getXRot(), 0.0F, 0.2F));
+                } else {
+                    double d0 = vec3d.horizontalDistance();
+                    double d1 = Math.signum(-vec3d.y) * Math.acos(d0 / vec3d.length()) * 57.2957763671875D;
+
+                    Fox.this.setXRot((float) d1);
+                }
+            }
+
+            if (entityliving != null && Fox.this.distanceTo(entityliving) <= 2.0F) {
+                Fox.this.doHurtTarget(entityliving);
+            } else if (Fox.this.getXRot() > 0.0F && Fox.this.onGround && (float) Fox.this.getDeltaMovement().y != 0.0F && Fox.this.level.getBlockState(Fox.this.blockPosition()).is(Blocks.SNOW)) {
+                Fox.this.setXRot(60.0F);
+                Fox.this.setTarget((LivingEntity) null);
+                Fox.this.setFaceplanted(true);
+            }
+
         }
     }
 
-    class FoxFollowParentGoal extends FollowParentGoal {
-        private final Fox fox;
+    private class SeekShelterGoal extends FleeSunGoal {
 
-        public FoxFollowParentGoal(Fox fox, double speed) {
-            super(fox, speed);
-            this.fox = fox;
+        private int interval = reducedTickDelay(100);
+
+        public SeekShelterGoal(double d0) {
+            super(Fox.this, d0);
         }
 
         @Override
         public boolean canUse() {
-            return !this.fox.isDefending() && super.canUse();
-        }
+            if (!Fox.this.isSleeping() && this.mob.getTarget() == null) {
+                if (Fox.this.level.isThundering() && Fox.this.level.canSeeSky(this.mob.blockPosition())) {
+                    return this.setWantedPos();
+                } else if (this.interval > 0) {
+                    --this.interval;
+                    return false;
+                } else {
+                    this.interval = 100;
+                    BlockPos blockposition = this.mob.blockPosition();
 
-        @Override
-        public boolean canContinueToUse() {
-            return !this.fox.isDefending() && super.canContinueToUse();
+                    return Fox.this.level.isDay() && Fox.this.level.canSeeSky(blockposition) && !((ServerLevel) Fox.this.level).isVillage(blockposition) && this.setWantedPos();
+                }
+            } else {
+                return false;
+            }
         }
 
         @Override
         public void start() {
-            this.fox.clearStates();
+            Fox.this.clearStates();
             super.start();
         }
     }
 
-    public static class FoxGroupData extends AgeableMob.AgeableMobGroupData {
-        public final Fox.Type type;
+    private class FoxMeleeAttackGoal extends MeleeAttackGoal {
 
-        public FoxGroupData(Fox.Type type) {
-            super(false);
-            this.type = type;
+        public FoxMeleeAttackGoal(double d0, boolean flag) {
+            super(Fox.this, d0, flag);
         }
-    }
 
-    class FoxLookAtPlayerGoal extends LookAtPlayerGoal {
-        public FoxLookAtPlayerGoal(Mob fox, Class<? extends LivingEntity> targetType, float range) {
-            super(fox, targetType, range);
+        @Override
+        protected void checkAndPerformAttack(LivingEntity target, double squaredDistance) {
+            double d1 = this.getAttackReachSqr(target);
+
+            if (squaredDistance <= d1 && this.isTimeToAttack()) {
+                this.resetAttackCooldown();
+                this.mob.doHurtTarget(target);
+                Fox.this.playSound(SoundEvents.FOX_BITE, 1.0F, 1.0F);
+            }
+
         }
 
         @Override
-        public boolean canUse() {
-            return super.canUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested();
+        public void start() {
+            Fox.this.setIsInterested(false);
+            super.start();
         }
 
         @Override
-        public boolean canContinueToUse() {
-            return super.canContinueToUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested();
+        public boolean canUse() {
+            return !Fox.this.isSitting() && !Fox.this.isSleeping() && !Fox.this.isCrouching() && !Fox.this.isFaceplanted() && super.canUse();
         }
     }
 
-    public class FoxLookControl extends LookControl {
-        public FoxLookControl() {
-            super(Fox.this);
-        }
+    private class SleepGoal extends Fox.FoxBehaviorGoal {
 
-        @Override
-        public void tick() {
-            if (!Fox.this.isSleeping()) {
-                super.tick();
-            }
+        private static final int WAIT_TIME_BEFORE_SLEEP = reducedTickDelay(140);
+        private int countdown;
 
+        public SleepGoal() {
+            super();
+            this.countdown = Fox.this.random.nextInt(Fox.SleepGoal.WAIT_TIME_BEFORE_SLEEP);
+            this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP));
         }
 
         @Override
-        protected boolean resetXRotOnTick() {
-            return !Fox.this.isPouncing() && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.isFaceplanted();
+        public boolean canUse() {
+            return Fox.this.xxa == 0.0F && Fox.this.yya == 0.0F && Fox.this.zza == 0.0F ? this.canSleep() || Fox.this.isSleeping() : false;
         }
-    }
 
-    class FoxMeleeAttackGoal extends MeleeAttackGoal {
-        public FoxMeleeAttackGoal(double speed, boolean pauseWhenIdle) {
-            super(Fox.this, speed, pauseWhenIdle);
+        @Override
+        public boolean canContinueToUse() {
+            return this.canSleep();
         }
 
-        @Override
-        protected void checkAndPerformAttack(LivingEntity target, double squaredDistance) {
-            double d = this.getAttackReachSqr(target);
-            if (squaredDistance <= d && this.isTimeToAttack()) {
-                this.resetAttackCooldown();
-                this.mob.doHurtTarget(target);
-                Fox.this.playSound(SoundEvents.FOX_BITE, 1.0F, 1.0F);
+        private boolean canSleep() {
+            if (this.countdown > 0) {
+                --this.countdown;
+                return false;
+            } else {
+                return Fox.this.level.isDay() && this.hasShelter() && !this.alertable() && !Fox.this.isInPowderSnow;
             }
+        }
 
+        @Override
+        public void stop() {
+            this.countdown = Fox.this.random.nextInt(Fox.SleepGoal.WAIT_TIME_BEFORE_SLEEP);
+            Fox.this.clearStates();
         }
 
         @Override
         public void start() {
+            Fox.this.setSitting(false);
+            Fox.this.setIsCrouching(false);
             Fox.this.setIsInterested(false);
-            super.start();
+            Fox.this.setJumping(false);
+            Fox.this.setSleeping(true);
+            Fox.this.getNavigation().stop();
+            Fox.this.getMoveControl().setWantedPosition(Fox.this.getX(), Fox.this.getY(), Fox.this.getZ(), 0.0D);
+        }
+    }
+
+    private class FoxFollowParentGoal extends FollowParentGoal {
+
+        private final Fox fox;
+
+        public FoxFollowParentGoal(Fox entityfox, double d0) {
+            super(entityfox, d0);
+            this.fox = entityfox;
         }
 
         @Override
         public boolean canUse() {
-            return !Fox.this.isSitting() && !Fox.this.isSleeping() && !Fox.this.isCrouching() && !Fox.this.isFaceplanted() && super.canUse();
+            return !this.fox.isDefending() && super.canUse();
         }
-    }
 
-    class FoxMoveControl extends MoveControl {
-        public FoxMoveControl() {
-            super(Fox.this);
+        @Override
+        public boolean canContinueToUse() {
+            return !this.fox.isDefending() && super.canContinueToUse();
         }
 
         @Override
-        public void tick() {
-            if (Fox.this.canMove()) {
-                super.tick();
-            }
-
+        public void start() {
+            this.fox.clearStates();
+            super.start();
         }
     }
 
-    class FoxPanicGoal extends PanicGoal {
-        public FoxPanicGoal(double speed) {
-            super(Fox.this, speed);
+    private class FoxStrollThroughVillageGoal extends StrollThroughVillageGoal {
+
+        public FoxStrollThroughVillageGoal(int i, int j) {
+            super(Fox.this, j);
         }
 
         @Override
-        public boolean shouldPanic() {
-            return !Fox.this.isDefending() && super.shouldPanic();
+        public void start() {
+            Fox.this.clearStates();
+            super.start();
         }
-    }
 
-    public class FoxPounceGoal extends JumpGoal {
         @Override
         public boolean canUse() {
-            if (!Fox.this.isFullyCrouched()) {
-                return false;
-            } else {
-                LivingEntity livingEntity = Fox.this.getTarget();
-                if (livingEntity != null && livingEntity.isAlive()) {
-                    if (livingEntity.getMotionDirection() != livingEntity.getDirection()) {
-                        return false;
-                    } else {
-                        boolean bl = Fox.isPathClear(Fox.this, livingEntity);
-                        if (!bl) {
-                            Fox.this.getNavigation().createPath(livingEntity, 0);
-                            Fox.this.setIsCrouching(false);
-                            Fox.this.setIsInterested(false);
-                        }
-
-                        return bl;
-                    }
-                } else {
-                    return false;
-                }
-            }
+            return super.canUse() && this.canFoxMove();
         }
 
         @Override
         public boolean canContinueToUse() {
-            LivingEntity livingEntity = Fox.this.getTarget();
-            if (livingEntity != null && livingEntity.isAlive()) {
-                double d = Fox.this.getDeltaMovement().y;
-                return (!(d * d < (double)0.05F) || !(Math.abs(Fox.this.getXRot()) < 15.0F) || !Fox.this.onGround) && !Fox.this.isFaceplanted();
-            } else {
-                return false;
-            }
+            return super.canContinueToUse() && this.canFoxMove();
         }
 
-        @Override
-        public boolean isInterruptable() {
-            return false;
+        private boolean canFoxMove() {
+            return !Fox.this.isSleeping() && !Fox.this.isSitting() && !Fox.this.isDefending() && Fox.this.getTarget() == null;
+        }
+    }
+
+    public class FoxEatBerriesGoal extends MoveToBlockGoal {
+
+        private static final int WAIT_TICKS = 40;
+        protected int ticksWaited;
+
+        public FoxEatBerriesGoal(double d0, int i, int j) {
+            super(Fox.this, d0, i, j);
         }
 
         @Override
-        public void start() {
-            Fox.this.setJumping(true);
-            Fox.this.setIsPouncing(true);
-            Fox.this.setIsInterested(false);
-            LivingEntity livingEntity = Fox.this.getTarget();
-            if (livingEntity != null) {
-                Fox.this.getLookControl().setLookAt(livingEntity, 60.0F, 30.0F);
-                Vec3 vec3 = (new Vec3(livingEntity.getX() - Fox.this.getX(), livingEntity.getY() - Fox.this.getY(), livingEntity.getZ() - Fox.this.getZ())).normalize();
-                Fox.this.setDeltaMovement(Fox.this.getDeltaMovement().add(vec3.x * 0.8D, 0.9D, vec3.z * 0.8D));
-            }
+        public double acceptedDistance() {
+            return 2.0D;
+        }
 
-            Fox.this.getNavigation().stop();
+        @Override
+        public boolean shouldRecalculatePath() {
+            return this.tryTicks % 100 == 0;
         }
 
         @Override
-        public void stop() {
-            Fox.this.setIsCrouching(false);
-            Fox.this.crouchAmount = 0.0F;
-            Fox.this.crouchAmountO = 0.0F;
-            Fox.this.setIsInterested(false);
-            Fox.this.setIsPouncing(false);
+        protected boolean isValidTarget(LevelReader world, BlockPos pos) {
+            BlockState iblockdata = world.getBlockState(pos);
+
+            return iblockdata.is(Blocks.SWEET_BERRY_BUSH) && (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE) >= 2 || CaveVines.hasGlowBerries(iblockdata);
         }
 
         @Override
         public void tick() {
-            LivingEntity livingEntity = Fox.this.getTarget();
-            if (livingEntity != null) {
-                Fox.this.getLookControl().setLookAt(livingEntity, 60.0F, 30.0F);
+            if (this.isReachedTarget()) {
+                if (this.ticksWaited >= 40) {
+                    this.onReachedTarget();
+                } else {
+                    ++this.ticksWaited;
+                }
+            } else if (!this.isReachedTarget() && Fox.this.random.nextFloat() < 0.05F) {
+                Fox.this.playSound(SoundEvents.FOX_SNIFF, 1.0F, 1.0F);
             }
 
-            if (!Fox.this.isFaceplanted()) {
-                Vec3 vec3 = Fox.this.getDeltaMovement();
-                if (vec3.y * vec3.y < (double)0.03F && Fox.this.getXRot() != 0.0F) {
-                    Fox.this.setXRot(Mth.rotlerp(Fox.this.getXRot(), 0.0F, 0.2F));
-                } else {
-                    double d = vec3.horizontalDistance();
-                    double e = Math.signum(-vec3.y) * Math.acos(d / vec3.length()) * (double)(180F / (float)Math.PI);
-                    Fox.this.setXRot((float)e);
+            super.tick();
+        }
+
+        protected void onReachedTarget() {
+            if (Fox.this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
+                BlockState iblockdata = Fox.this.level.getBlockState(this.blockPos);
+
+                if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) {
+                    this.pickSweetBerries(iblockdata);
+                } else if (CaveVines.hasGlowBerries(iblockdata)) {
+                    this.pickGlowBerry(iblockdata);
                 }
+
             }
+        }
 
-            if (livingEntity != null && Fox.this.distanceTo(livingEntity) <= 2.0F) {
-                Fox.this.doHurtTarget(livingEntity);
-            } else if (Fox.this.getXRot() > 0.0F && Fox.this.onGround && (float)Fox.this.getDeltaMovement().y != 0.0F && Fox.this.level.getBlockState(Fox.this.blockPosition()).is(Blocks.SNOW)) {
-                Fox.this.setXRot(60.0F);
-                Fox.this.setTarget((LivingEntity)null);
-                Fox.this.setFaceplanted(true);
+        private void pickGlowBerry(BlockState state) {
+            CaveVines.use(state, Fox.this.level, this.blockPos, Fox.this); // CraftBukkit
+        }
+
+        private void pickSweetBerries(BlockState state) {
+            int i = (Integer) state.getValue(SweetBerryBushBlock.AGE);
+
+            state.setValue(SweetBerryBushBlock.AGE, 1);
+            // CraftBukkit start - call EntityChangeBlockEvent
+            if (org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callEntityChangeBlockEvent(Fox.this, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1)).isCancelled()) {
+                return;
             }
+            // CraftBukkit end
+            int j = 1 + Fox.this.level.random.nextInt(2) + (i == 3 ? 1 : 0);
+            ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND);
 
+            if (itemstack.isEmpty()) {
+                Fox.this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.SWEET_BERRIES));
+                --j;
+            }
+
+            if (j > 0) {
+                Block.popResource(Fox.this.level, this.blockPos, new ItemStack(Items.SWEET_BERRIES, j));
+            }
+
+            Fox.this.playSound(SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, 1.0F, 1.0F);
+            Fox.this.level.setBlock(this.blockPos, (BlockState) state.setValue(SweetBerryBushBlock.AGE, 1), 2);
+        }
+
+        @Override
+        public boolean canUse() {
+            return !Fox.this.isSleeping() && super.canUse();
+        }
+
+        @Override
+        public void start() {
+            this.ticksWaited = 0;
+            Fox.this.setSitting(false);
+            super.start();
         }
     }
 
-    class FoxSearchForItemsGoal extends Goal {
+    private class FoxSearchForItemsGoal extends Goal {
+
         public FoxSearchForItemsGoal() {
             this.setFlags(EnumSet.of(Goal.Flag.MOVE));
         }
@@ -1220,6 +1364,7 @@
                     return false;
                 } else {
                     List<ItemEntity> list = Fox.this.level.getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS);
+
                     return !list.isEmpty() && Fox.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty();
                 }
             } else {
@@ -1230,9 +1375,10 @@
         @Override
         public void tick() {
             List<ItemEntity> list = Fox.this.level.getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS);
-            ItemStack itemStack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND);
-            if (itemStack.isEmpty() && !list.isEmpty()) {
-                Fox.this.getNavigation().moveTo(list.get(0), (double)1.2F);
+            ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND);
+
+            if (itemstack.isEmpty() && !list.isEmpty()) {
+                Fox.this.getNavigation().moveTo((Entity) list.get(0), 1.2000000476837158D);
             }
 
         }
@@ -1240,46 +1386,40 @@
         @Override
         public void start() {
             List<ItemEntity> list = Fox.this.level.getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS);
+
             if (!list.isEmpty()) {
-                Fox.this.getNavigation().moveTo(list.get(0), (double)1.2F);
+                Fox.this.getNavigation().moveTo((Entity) list.get(0), 1.2000000476837158D);
             }
 
         }
     }
 
-    class FoxStrollThroughVillageGoal extends StrollThroughVillageGoal {
-        public FoxStrollThroughVillageGoal(int unused, int searchRange) {
-            super(Fox.this, searchRange);
-        }
+    private class FoxLookAtPlayerGoal extends LookAtPlayerGoal {
 
-        @Override
-        public void start() {
-            Fox.this.clearStates();
-            super.start();
+        public FoxLookAtPlayerGoal(Mob mob, Class targetType, float range) {
+            super(mob, targetType, range);
         }
 
         @Override
         public boolean canUse() {
-            return super.canUse() && this.canFoxMove();
+            return super.canUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested();
         }
 
         @Override
         public boolean canContinueToUse() {
-            return super.canContinueToUse() && this.canFoxMove();
-        }
-
-        private boolean canFoxMove() {
-            return !Fox.this.isSleeping() && !Fox.this.isSitting() && !Fox.this.isDefending() && Fox.this.getTarget() == null;
+            return super.canContinueToUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested();
         }
     }
 
-    class PerchAndSearchGoal extends Fox.FoxBehaviorGoal {
+    private class PerchAndSearchGoal extends Fox.FoxBehaviorGoal {
+
         private double relX;
         private double relZ;
         private int lookTime;
         private int looksRemaining;
 
         public PerchAndSearchGoal() {
+            super();
             this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
         }
 
@@ -1314,163 +1454,86 @@
                 this.resetLook();
             }
 
-            Fox.this.getLookControl().setLookAt(Fox.this.getX() + this.relX, Fox.this.getEyeY(), Fox.this.getZ() + this.relZ, (float)Fox.this.getMaxHeadYRot(), (float)Fox.this.getMaxHeadXRot());
+            Fox.this.getLookControl().setLookAt(Fox.this.getX() + this.relX, Fox.this.getEyeY(), Fox.this.getZ() + this.relZ, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot());
         }
 
         private void resetLook() {
-            double d = (Math.PI * 2D) * Fox.this.getRandom().nextDouble();
-            this.relX = Math.cos(d);
-            this.relZ = Math.sin(d);
+            double d0 = 6.283185307179586D * Fox.this.getRandom().nextDouble();
+
+            this.relX = Math.cos(d0);
+            this.relZ = Math.sin(d0);
             this.lookTime = this.adjustedTickDelay(80 + Fox.this.getRandom().nextInt(20));
         }
     }
 
-    class SeekShelterGoal extends FleeSunGoal {
-        private int interval = reducedTickDelay(100);
-
-        public SeekShelterGoal(double speed) {
-            super(Fox.this, speed);
-        }
-
-        @Override
-        public boolean canUse() {
-            if (!Fox.this.isSleeping() && this.mob.getTarget() == null) {
-                if (Fox.this.level.isThundering() && Fox.this.level.canSeeSky(this.mob.blockPosition())) {
-                    return this.setWantedPos();
-                } else if (this.interval > 0) {
-                    --this.interval;
-                    return false;
-                } else {
-                    this.interval = 100;
-                    BlockPos blockPos = this.mob.blockPosition();
-                    return Fox.this.level.isDay() && Fox.this.level.canSeeSky(blockPos) && !((ServerLevel)Fox.this.level).isVillage(blockPos) && this.setWantedPos();
-                }
-            } else {
-                return false;
-            }
-        }
-
-        @Override
-        public void start() {
-            Fox.this.clearStates();
-            super.start();
-        }
-    }
+    private class DefendTrustedTargetGoal extends NearestAttackableTargetGoal<LivingEntity> {
 
-    class SleepGoal extends Fox.FoxBehaviorGoal {
-        private static final int WAIT_TIME_BEFORE_SLEEP = reducedTickDelay(140);
-        private int countdown = Fox.this.random.nextInt(WAIT_TIME_BEFORE_SLEEP);
+        @Nullable
+        private LivingEntity trustedLastHurtBy;
+        @Nullable
+        private LivingEntity trustedLastHurt;
+        private int timestamp;
 
-        public SleepGoal() {
-            this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP));
+        public DefendTrustedTargetGoal(Class oclass, boolean flag, boolean flag1, @Nullable Predicate<LivingEntity> predicate) { // CraftBukkit - decompile error
+            super(Fox.this, oclass, 10, flag, flag1, predicate);
         }
 
         @Override
         public boolean canUse() {
-            if (Fox.this.xxa == 0.0F && Fox.this.yya == 0.0F && Fox.this.zza == 0.0F) {
-                return this.canSleep() || Fox.this.isSleeping();
-            } else {
+            if (this.randomInterval > 0 && this.mob.getRandom().nextInt(this.randomInterval) != 0) {
                 return false;
-            }
-        }
+            } else {
+                Iterator iterator = Fox.this.getTrustedUUIDs().iterator();
 
-        @Override
-        public boolean canContinueToUse() {
-            return this.canSleep();
-        }
+                while (iterator.hasNext()) {
+                    UUID uuid = (UUID) iterator.next();
 
-        private boolean canSleep() {
-            if (this.countdown > 0) {
-                --this.countdown;
-                return false;
-            } else {
-                return Fox.this.level.isDay() && this.hasShelter() && !this.alertable() && !Fox.this.isInPowderSnow;
-            }
-        }
+                    if (uuid != null && Fox.this.level instanceof ServerLevel) {
+                        Entity entity = ((ServerLevel) Fox.this.level).getEntity(uuid);
 
-        @Override
-        public void stop() {
-            this.countdown = Fox.this.random.nextInt(WAIT_TIME_BEFORE_SLEEP);
-            Fox.this.clearStates();
-        }
+                        if (entity instanceof LivingEntity) {
+                            LivingEntity entityliving = (LivingEntity) entity;
 
-        @Override
-        public void start() {
-            Fox.this.setSitting(false);
-            Fox.this.setIsCrouching(false);
-            Fox.this.setIsInterested(false);
-            Fox.this.setJumping(false);
-            Fox.this.setSleeping(true);
-            Fox.this.getNavigation().stop();
-            Fox.this.getMoveControl().setWantedPosition(Fox.this.getX(), Fox.this.getY(), Fox.this.getZ(), 0.0D);
-        }
-    }
+                            this.trustedLastHurt = entityliving;
+                            this.trustedLastHurtBy = entityliving.getLastHurtByMob();
+                            int i = entityliving.getLastHurtByMobTimestamp();
 
-    class StalkPreyGoal extends Goal {
-        public StalkPreyGoal() {
-            this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
-        }
+                            return i != this.timestamp && this.canAttack(this.trustedLastHurtBy, this.targetConditions);
+                        }
+                    }
+                }
 
-        @Override
-        public boolean canUse() {
-            if (Fox.this.isSleeping()) {
                 return false;
-            } else {
-                LivingEntity livingEntity = Fox.this.getTarget();
-                return livingEntity != null && livingEntity.isAlive() && Fox.STALKABLE_PREY.test(livingEntity) && Fox.this.distanceToSqr(livingEntity) > 36.0D && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.jumping;
             }
         }
 
         @Override
         public void start() {
-            Fox.this.setSitting(false);
-            Fox.this.setFaceplanted(false);
-        }
-
-        @Override
-        public void stop() {
-            LivingEntity livingEntity = Fox.this.getTarget();
-            if (livingEntity != null && Fox.isPathClear(Fox.this, livingEntity)) {
-                Fox.this.setIsInterested(true);
-                Fox.this.setIsCrouching(true);
-                Fox.this.getNavigation().stop();
-                Fox.this.getLookControl().setLookAt(livingEntity, (float)Fox.this.getMaxHeadYRot(), (float)Fox.this.getMaxHeadXRot());
-            } else {
-                Fox.this.setIsInterested(false);
-                Fox.this.setIsCrouching(false);
+            this.setTarget(this.trustedLastHurtBy);
+            this.target = this.trustedLastHurtBy;
+            if (this.trustedLastHurt != null) {
+                this.timestamp = this.trustedLastHurt.getLastHurtByMobTimestamp();
             }
 
-        }
-
-        @Override
-        public void tick() {
-            LivingEntity livingEntity = Fox.this.getTarget();
-            if (livingEntity != null) {
-                Fox.this.getLookControl().setLookAt(livingEntity, (float)Fox.this.getMaxHeadYRot(), (float)Fox.this.getMaxHeadXRot());
-                if (Fox.this.distanceToSqr(livingEntity) <= 36.0D) {
-                    Fox.this.setIsInterested(true);
-                    Fox.this.setIsCrouching(true);
-                    Fox.this.getNavigation().stop();
-                } else {
-                    Fox.this.getNavigation().moveTo(livingEntity, 1.5D);
-                }
-
-            }
+            Fox.this.playSound(SoundEvents.FOX_AGGRO, 1.0F, 1.0F);
+            Fox.this.setDefending(true);
+            Fox.this.wakeUp();
+            super.start();
         }
     }
 
     public static enum Type implements StringRepresentable {
-        RED(0, "red"),
-        SNOW(1, "snow");
+
+        RED(0, "red"), SNOW(1, "snow");
 
         public static final StringRepresentable.EnumCodec<Fox.Type> CODEC = StringRepresentable.fromEnum(Fox.Type::values);
         private static final IntFunction<Fox.Type> BY_ID = ByIdMap.continuous(Fox.Type::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO);
         private final int id;
         private final String name;
 
-        private Type(int id, String key) {
-            this.id = id;
-            this.name = key;
+        private Type(int i, String s) {
+            this.id = i;
+            this.name = s;
         }
 
         @Override
@@ -1483,15 +1546,51 @@
         }
 
         public static Fox.Type byName(String name) {
-            return CODEC.byName(name, RED);
+            return (Fox.Type) Fox.Type.CODEC.byName(name, Fox.Type.RED);
         }
 
         public static Fox.Type byId(int id) {
-            return BY_ID.apply(id);
+            return (Fox.Type) Fox.Type.BY_ID.apply(id);
         }
 
         public static Fox.Type byBiome(Holder<Biome> biome) {
-            return biome.value().getPrecipitation() == Biome.Precipitation.SNOW ? SNOW : RED;
+            return ((Biome) biome.value()).getPrecipitation() == Biome.Precipitation.SNOW ? Fox.Type.SNOW : Fox.Type.RED;
+        }
+    }
+
+    public static class FoxGroupData extends AgeableMob.AgeableMobGroupData {
+
+        public final Fox.Type type;
+
+        public FoxGroupData(Fox.Type type) {
+            super(false);
+            this.type = type;
+        }
+    }
+
+    private abstract class FoxBehaviorGoal extends Goal {
+
+        private final TargetingConditions alertableTargeting = TargetingConditions.forCombat().range(12.0D).ignoreLineOfSight().selector(Fox.this.new FoxAlertableEntitiesSelector());
+
+        FoxBehaviorGoal() {}
+
+        protected boolean hasShelter() {
+            BlockPos blockposition = new BlockPos(Fox.this.getX(), Fox.this.getBoundingBox().maxY, Fox.this.getZ());
+
+            return !Fox.this.level.canSeeSky(blockposition) && Fox.this.getWalkTargetValue(blockposition) >= 0.0F;
+        }
+
+        protected boolean alertable() {
+            return !Fox.this.level.getNearbyEntities(LivingEntity.class, this.alertableTargeting, Fox.this, Fox.this.getBoundingBox().inflate(12.0D, 6.0D, 12.0D)).isEmpty();
+        }
+    }
+
+    public class FoxAlertableEntitiesSelector implements Predicate<LivingEntity> {
+
+        public FoxAlertableEntitiesSelector() {}
+
+        public boolean test(LivingEntity entityliving) {
+            return entityliving instanceof Fox ? false : (!(entityliving instanceof Chicken) && !(entityliving instanceof Rabbit) && !(entityliving instanceof Monster) ? (entityliving instanceof TamableAnimal ? !((TamableAnimal) entityliving).isTame() : (entityliving instanceof Player && (entityliving.isSpectator() || ((Player) entityliving).isCreative()) ? false : (Fox.this.trusts(entityliving.getUUID()) ? false : !entityliving.isSleeping() && !entityliving.isDiscrete()))) : true);
         }
     }
 }
