--- a/net/minecraft/world/entity/animal/Cat.java
+++ b/net/minecraft/world/entity/animal/Cat.java
@@ -1,10 +1,14 @@
 package net.minecraft.world.entity.animal;
 
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Predicate;
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Holder;
+import net.minecraft.core.Registry;
 import net.minecraft.core.component.DataComponents;
 import net.minecraft.core.registries.BuiltInRegistries;
 import net.minecraft.core.registries.Registries;
@@ -29,6 +33,7 @@
 import net.minecraft.world.InteractionResult;
 import net.minecraft.world.damagesource.DamageSource;
 import net.minecraft.world.entity.AgeableMob;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EntitySelector;
 import net.minecraft.world.entity.EntityType;
 import net.minecraft.world.entity.LivingEntity;
@@ -73,9 +78,10 @@
 import net.minecraft.world.phys.AABB;
 
 public class Cat extends TamableAnimal implements VariantHolder<Holder<CatVariant>> {
-    public static final double TEMPT_SPEED_MOD = 0.6;
-    public static final double WALK_SPEED_MOD = 0.8;
-    public static final double SPRINT_SPEED_MOD = 1.33;
+
+    public static final double TEMPT_SPEED_MOD = 0.6D;
+    public static final double WALK_SPEED_MOD = 0.8D;
+    public static final double SPRINT_SPEED_MOD = 1.33D;
     private static final EntityDataAccessor<Holder<CatVariant>> DATA_VARIANT_ID = SynchedEntityData.defineId(Cat.class, EntityDataSerializers.CAT_VARIANT);
     private static final EntityDataAccessor<Boolean> IS_LYING = SynchedEntityData.defineId(Cat.class, EntityDataSerializers.BOOLEAN);
     private static final EntityDataAccessor<Boolean> RELAX_STATE_ONE = SynchedEntityData.defineId(Cat.class, EntityDataSerializers.BOOLEAN);
@@ -98,99 +104,105 @@
     }
 
     public ResourceLocation getTextureId() {
-        return this.getVariant().value().texture();
+        return ((CatVariant) this.getVariant().value()).texture();
     }
 
     @Override
     protected void registerGoals() {
-        this.temptGoal = new Cat.CatTemptGoal(this, 0.6, stack -> stack.is(ItemTags.CAT_FOOD), true);
+        this.temptGoal = new Cat.CatTemptGoal(this, 0.6D, (itemstack) -> {
+            return itemstack.is(ItemTags.CAT_FOOD);
+        }, true);
         this.goalSelector.addGoal(1, new FloatGoal(this));
-        this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5));
+        this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5D));
         this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
         this.goalSelector.addGoal(3, new Cat.CatRelaxOnOwnerGoal(this));
         this.goalSelector.addGoal(4, this.temptGoal);
-        this.goalSelector.addGoal(5, new CatLieOnBedGoal(this, 1.1, 8));
-        this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 5.0F));
-        this.goalSelector.addGoal(7, new CatSitOnBlockGoal(this, 0.8));
+        this.goalSelector.addGoal(5, new CatLieOnBedGoal(this, 1.1D, 8));
+        this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0D, 10.0F, 5.0F));
+        this.goalSelector.addGoal(7, new CatSitOnBlockGoal(this, 0.8D));
         this.goalSelector.addGoal(8, new LeapAtTargetGoal(this, 0.3F));
         this.goalSelector.addGoal(9, new OcelotAttackGoal(this));
-        this.goalSelector.addGoal(10, new BreedGoal(this, 0.8));
-        this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8, 1.0000001E-5F));
+        this.goalSelector.addGoal(10, new BreedGoal(this, 0.8D));
+        this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F));
         this.goalSelector.addGoal(12, new LookAtPlayerGoal(this, Player.class, 10.0F));
-        this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, null));
+        this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, (Predicate) null));
         this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR));
     }
 
     @Override
     public Holder<CatVariant> getVariant() {
-        return this.entityData.get(DATA_VARIANT_ID);
+        return (Holder) this.entityData.get(Cat.DATA_VARIANT_ID);
     }
 
-    @Override
     public void setVariant(Holder<CatVariant> holder) {
-        this.entityData.set(DATA_VARIANT_ID, holder);
+        this.entityData.set(Cat.DATA_VARIANT_ID, holder);
     }
 
     public void setLying(boolean sleeping) {
-        this.entityData.set(IS_LYING, sleeping);
+        this.entityData.set(Cat.IS_LYING, sleeping);
     }
 
     public boolean isLying() {
-        return this.entityData.get(IS_LYING);
+        return (Boolean) this.entityData.get(Cat.IS_LYING);
     }
 
     public void setRelaxStateOne(boolean headDown) {
-        this.entityData.set(RELAX_STATE_ONE, headDown);
+        this.entityData.set(Cat.RELAX_STATE_ONE, headDown);
     }
 
     public boolean isRelaxStateOne() {
-        return this.entityData.get(RELAX_STATE_ONE);
+        return (Boolean) this.entityData.get(Cat.RELAX_STATE_ONE);
     }
 
     public DyeColor getCollarColor() {
-        return DyeColor.byId(this.entityData.get(DATA_COLLAR_COLOR));
+        return DyeColor.byId((Integer) this.entityData.get(Cat.DATA_COLLAR_COLOR));
     }
 
     public void setCollarColor(DyeColor color) {
-        this.entityData.set(DATA_COLLAR_COLOR, color.getId());
+        this.entityData.set(Cat.DATA_COLLAR_COLOR, color.getId());
     }
 
     @Override
     protected void defineSynchedData(SynchedEntityData.Builder builder) {
         super.defineSynchedData(builder);
-        builder.define(DATA_VARIANT_ID, BuiltInRegistries.CAT_VARIANT.getHolderOrThrow(DEFAULT_VARIANT));
-        builder.define(IS_LYING, false);
-        builder.define(RELAX_STATE_ONE, false);
-        builder.define(DATA_COLLAR_COLOR, DyeColor.RED.getId());
+        builder.define(Cat.DATA_VARIANT_ID, BuiltInRegistries.CAT_VARIANT.getHolderOrThrow(Cat.DEFAULT_VARIANT));
+        builder.define(Cat.IS_LYING, false);
+        builder.define(Cat.RELAX_STATE_ONE, false);
+        builder.define(Cat.DATA_COLLAR_COLOR, DyeColor.RED.getId());
     }
 
     @Override
     public void addAdditionalSaveData(CompoundTag nbt) {
         super.addAdditionalSaveData(nbt);
-        nbt.putString("variant", this.getVariant().unwrapKey().orElse(DEFAULT_VARIANT).location().toString());
-        nbt.putByte("CollarColor", (byte)this.getCollarColor().getId());
+        nbt.putString("variant", ((ResourceKey) this.getVariant().unwrapKey().orElse(Cat.DEFAULT_VARIANT)).location().toString());
+        nbt.putByte("CollarColor", (byte) this.getCollarColor().getId());
     }
 
     @Override
     public void readAdditionalSaveData(CompoundTag nbt) {
         super.readAdditionalSaveData(nbt);
-        Optional.ofNullable(ResourceLocation.tryParse(nbt.getString("variant")))
-            .map(id -> ResourceKey.create(Registries.CAT_VARIANT, id))
-            .flatMap(BuiltInRegistries.CAT_VARIANT::getHolder)
-            .ifPresent(this::setVariant);
+        Optional<ResourceKey<CatVariant>> optional = Optional.ofNullable(ResourceLocation.tryParse(nbt.getString("variant"))).map((minecraftkey) -> { // CraftBukkit - decompile error
+            return ResourceKey.create(Registries.CAT_VARIANT, minecraftkey);
+        });
+        Registry<CatVariant> iregistry = BuiltInRegistries.CAT_VARIANT; // CraftBukkit - decompile error
+
+        Objects.requireNonNull(iregistry);
+        optional.flatMap(iregistry::getHolder).ifPresent(this::setVariant);
         if (nbt.contains("CollarColor", 99)) {
             this.setCollarColor(DyeColor.byId(nbt.getInt("CollarColor")));
         }
+
     }
 
     @Override
     public void customServerAiStep() {
         if (this.getMoveControl().hasWanted()) {
-            double d = this.getMoveControl().getSpeedModifier();
-            if (d == 0.6) {
+            double d0 = this.getMoveControl().getSpeedModifier();
+
+            if (d0 == 0.6D) {
                 this.setPose(Pose.CROUCHING);
                 this.setSprinting(false);
-            } else if (d == 1.33) {
+            } else if (d0 == 1.33D) {
                 this.setPose(Pose.STANDING);
                 this.setSprinting(true);
             } else {
@@ -201,20 +213,13 @@
             this.setPose(Pose.STANDING);
             this.setSprinting(false);
         }
+
     }
 
     @Nullable
     @Override
     protected SoundEvent getAmbientSound() {
-        if (this.isTame()) {
-            if (this.isInLove()) {
-                return SoundEvents.CAT_PURR;
-            } else {
-                return this.random.nextInt(4) == 0 ? SoundEvents.CAT_PURREOW : SoundEvents.CAT_AMBIENT;
-            }
-        } else {
-            return SoundEvents.CAT_STRAY_AMBIENT;
-        }
+        return this.isTame() ? (this.isInLove() ? SoundEvents.CAT_PURR : (this.random.nextInt(4) == 0 ? SoundEvents.CAT_PURREOW : SoundEvents.CAT_AMBIENT)) : SoundEvents.CAT_STRAY_AMBIENT;
     }
 
     @Override
@@ -237,7 +242,7 @@
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.ATTACK_DAMAGE, 3.0);
+        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 3.0D);
     }
 
     @Override
@@ -278,6 +283,7 @@
             this.lieDownAmount = Math.max(0.0F, this.lieDownAmount - 0.22F);
             this.lieDownAmountTail = Math.max(0.0F, this.lieDownAmountTail - 0.13F);
         }
+
     }
 
     private void updateRelaxStateOneAmount() {
@@ -287,6 +293,7 @@
         } else {
             this.relaxStateOneAmount = Math.max(0.0F, this.relaxStateOneAmount - 0.13F);
         }
+
     }
 
     public float getLieDownAmount(float tickDelta) {
@@ -303,44 +310,55 @@
 
     @Nullable
     @Override
-    public Cat getBreedOffspring(ServerLevel serverLevel, AgeableMob ageableMob) {
-        Cat cat = EntityType.CAT.create(serverLevel);
-        if (cat != null && ageableMob instanceof Cat cat2) {
+    public Cat getBreedOffspring(ServerLevel world, AgeableMob entity) {
+        Cat entitycat = (Cat) EntityType.CAT.create(world);
+
+        if (entitycat != null && entity instanceof Cat entitycat1) {
             if (this.random.nextBoolean()) {
-                cat.setVariant(this.getVariant());
+                entitycat.setVariant(this.getVariant());
             } else {
-                cat.setVariant(cat2.getVariant());
+                entitycat.setVariant(entitycat1.getVariant());
             }
 
             if (this.isTame()) {
-                cat.setOwnerUUID(this.getOwnerUUID());
-                cat.setTame(true, true);
+                entitycat.setOwnerUUID(this.getOwnerUUID());
+                entitycat.setTame(true, true);
                 if (this.random.nextBoolean()) {
-                    cat.setCollarColor(this.getCollarColor());
+                    entitycat.setCollarColor(this.getCollarColor());
                 } else {
-                    cat.setCollarColor(cat2.getCollarColor());
+                    entitycat.setCollarColor(entitycat1.getCollarColor());
                 }
             }
         }
 
-        return cat;
+        return entitycat;
     }
 
     @Override
     public boolean canMate(Animal other) {
-        return this.isTame() && other instanceof Cat cat && cat.isTame() && super.canMate(other);
+        if (!this.isTame()) {
+            return false;
+        } else if (!(other instanceof Cat)) {
+            return false;
+        } else {
+            Cat entitycat = (Cat) other;
+
+            return entitycat.isTame() && super.canMate(other);
+        }
     }
 
     @Nullable
     @Override
     public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData) {
         entityData = super.finalizeSpawn(world, difficulty, spawnReason, entityData);
-        boolean bl = world.getMoonBrightness() > 0.9F;
-        TagKey<CatVariant> tagKey = bl ? CatVariantTags.FULL_MOON_SPAWNS : CatVariantTags.DEFAULT_SPAWNS;
-        BuiltInRegistries.CAT_VARIANT.getRandomElementOf(tagKey, world.getRandom()).ifPresent(this::setVariant);
-        ServerLevel serverLevel = world.getLevel();
-        if (serverLevel.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) {
-            this.setVariant(BuiltInRegistries.CAT_VARIANT.getHolderOrThrow(CatVariant.ALL_BLACK));
+        boolean flag = world.getMoonBrightness() > 0.9F;
+        TagKey<CatVariant> tagkey = flag ? CatVariantTags.FULL_MOON_SPAWNS : CatVariantTags.DEFAULT_SPAWNS;
+
+        BuiltInRegistries.CAT_VARIANT.getRandomElementOf(tagkey, world.getRandom()).ifPresent(this::setVariant);
+        ServerLevel worldserver = world.getLevel();
+
+        if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK, world).isValid()) { // Paper - Fix swamp hut cat generation deadlock
+            this.setVariant((Holder) BuiltInRegistries.CAT_VARIANT.getHolderOrThrow(CatVariant.ALL_BLACK));
             this.setPersistenceRequired();
         }
 
@@ -349,42 +367,54 @@
 
     @Override
     public InteractionResult mobInteract(Player player, InteractionHand hand) {
-        ItemStack itemStack = player.getItemInHand(hand);
-        Item item = itemStack.getItem();
+        ItemStack itemstack = player.getItemInHand(hand);
+        Item item = itemstack.getItem();
+        InteractionResult enuminteractionresult;
+
         if (this.isTame()) {
             if (this.isOwnedBy(player)) {
-                if (item instanceof DyeItem dyeItem) {
-                    DyeColor dyeColor = dyeItem.getDyeColor();
-                    if (dyeColor != this.getCollarColor()) {
+                if (item instanceof DyeItem) {
+                    DyeItem itemdye = (DyeItem) item;
+                    DyeColor enumcolor = itemdye.getDyeColor();
+
+                    if (enumcolor != this.getCollarColor()) {
+                        // Paper start - Add EntityDyeEvent and CollarColorable interface
+                        final io.papermc.paper.event.entity.EntityDyeEvent event = new io.papermc.paper.event.entity.EntityDyeEvent(this.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData((byte) enumcolor.getId()), ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity());
+                        if (!event.callEvent()) {
+                            return InteractionResult.FAIL;
+                        }
+                        enumcolor = DyeColor.byId(event.getColor().getWoolData());
+                        // Paper end - Add EntityDyeEvent and CollarColorable interface
                         if (!this.level().isClientSide()) {
-                            this.setCollarColor(dyeColor);
-                            itemStack.consume(1, player);
+                            this.setCollarColor(enumcolor);
+                            itemstack.consume(1, player);
                             this.setPersistenceRequired();
                         }
 
                         return InteractionResult.sidedSuccess(this.level().isClientSide());
                     }
-                } else if (this.isFood(itemStack) && this.getHealth() < this.getMaxHealth()) {
+                } else if (this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) {
                     if (!this.level().isClientSide()) {
-                        this.usePlayerItem(player, hand, itemStack);
-                        FoodProperties foodProperties = itemStack.get(DataComponents.FOOD);
-                        this.heal(foodProperties != null ? (float)foodProperties.nutrition() : 1.0F);
+                        this.usePlayerItem(player, hand, itemstack);
+                        FoodProperties foodinfo = (FoodProperties) itemstack.get(DataComponents.FOOD);
+
+                        this.heal(foodinfo != null ? (float) foodinfo.nutrition() : 1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper - Add missing regain reason
                     }
 
                     return InteractionResult.sidedSuccess(this.level().isClientSide());
                 }
 
-                InteractionResult interactionResult = super.mobInteract(player, hand);
-                if (!interactionResult.consumesAction()) {
+                enuminteractionresult = super.mobInteract(player, hand);
+                if (!enuminteractionresult.consumesAction()) {
                     this.setOrderedToSit(!this.isOrderedToSit());
                     return InteractionResult.sidedSuccess(this.level().isClientSide());
                 }
 
-                return interactionResult;
+                return enuminteractionresult;
             }
-        } else if (this.isFood(itemStack)) {
+        } else if (this.isFood(itemstack)) {
             if (!this.level().isClientSide()) {
-                this.usePlayerItem(player, hand, itemStack);
+                this.usePlayerItem(player, hand, itemstack);
                 this.tryToTame(player);
                 this.setPersistenceRequired();
             }
@@ -392,12 +422,12 @@
             return InteractionResult.sidedSuccess(this.level().isClientSide());
         }
 
-        InteractionResult interactionResult2 = super.mobInteract(player, hand);
-        if (interactionResult2.consumesAction()) {
+        enuminteractionresult = super.mobInteract(player, hand);
+        if (enuminteractionresult.consumesAction()) {
             this.setPersistenceRequired();
         }
 
-        return interactionResult2;
+        return enuminteractionresult;
     }
 
     @Override
@@ -418,23 +448,25 @@
 
     protected void reassessTameGoals() {
         if (this.avoidPlayersGoal == null) {
-            this.avoidPlayersGoal = new Cat.CatAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8, 1.33);
+            this.avoidPlayersGoal = new Cat.CatAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8D, 1.33D);
         }
 
         this.goalSelector.removeGoal(this.avoidPlayersGoal);
         if (!this.isTame()) {
             this.goalSelector.addGoal(4, this.avoidPlayersGoal);
         }
+
     }
 
     private void tryToTame(Player player) {
-        if (this.random.nextInt(3) == 0) {
+        if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
             this.tame(player);
             this.setOrderedToSit(true);
-            this.level().broadcastEntityEvent(this, (byte)7);
+            this.level().broadcastEntityEvent(this, (byte) 7);
         } else {
-            this.level().broadcastEntityEvent(this, (byte)6);
+            this.level().broadcastEntityEvent(this, (byte) 6);
         }
+
     }
 
     @Override
@@ -442,26 +474,41 @@
         return this.isCrouching() || super.isSteppingCarefully();
     }
 
-    static class CatAvoidEntityGoal<T extends LivingEntity> extends AvoidEntityGoal<T> {
+    private static class CatTemptGoal extends TemptGoal {
+
+        @Nullable
+        private LivingEntity selectedPlayer; // CraftBukkit
         private final Cat cat;
 
-        public CatAvoidEntityGoal(Cat cat, Class<T> fleeFromType, float distance, double slowSpeed, double fastSpeed) {
-            super(cat, fleeFromType, distance, slowSpeed, fastSpeed, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test);
+        public CatTemptGoal(Cat cat, double speed, Predicate<ItemStack> foodPredicate, boolean canBeScared) {
+            super(cat, speed, foodPredicate, canBeScared);
             this.cat = cat;
         }
 
         @Override
-        public boolean canUse() {
-            return !this.cat.isTame() && super.canUse();
+        public void tick() {
+            super.tick();
+            if (this.selectedPlayer == null && this.mob.getRandom().nextInt(this.adjustedTickDelay(600)) == 0) {
+                this.selectedPlayer = this.player;
+            } else if (this.mob.getRandom().nextInt(this.adjustedTickDelay(500)) == 0) {
+                this.selectedPlayer = null;
+            }
+
         }
 
         @Override
-        public boolean canContinueToUse() {
-            return !this.cat.isTame() && super.canContinueToUse();
+        protected boolean canScare() {
+            return this.selectedPlayer != null && this.selectedPlayer.equals(this.player) ? false : super.canScare();
+        }
+
+        @Override
+        public boolean canUse() {
+            return super.canUse() && !this.cat.isTame();
         }
     }
 
-    static class CatRelaxOnOwnerGoal extends Goal {
+    private static class CatRelaxOnOwnerGoal extends Goal {
+
         private final Cat cat;
         @Nullable
         private Player ownerPlayer;
@@ -480,23 +527,27 @@
             } else if (this.cat.isOrderedToSit()) {
                 return false;
             } else {
-                LivingEntity livingEntity = this.cat.getOwner();
-                if (livingEntity instanceof Player) {
-                    this.ownerPlayer = (Player)livingEntity;
-                    if (!livingEntity.isSleeping()) {
+                LivingEntity entityliving = this.cat.getOwner();
+
+                if (entityliving instanceof Player) {
+                    this.ownerPlayer = (Player) entityliving;
+                    if (!entityliving.isSleeping()) {
                         return false;
                     }
 
-                    if (this.cat.distanceToSqr(this.ownerPlayer) > 100.0) {
+                    if (this.cat.distanceToSqr((Entity) this.ownerPlayer) > 100.0D) {
                         return false;
                     }
 
-                    BlockPos blockPos = this.ownerPlayer.blockPosition();
-                    BlockState blockState = this.cat.level().getBlockState(blockPos);
-                    if (blockState.is(BlockTags.BEDS)) {
-                        this.goalPos = blockState.getOptionalValue(BedBlock.FACING)
-                            .map(direction -> blockPos.relative(direction.getOpposite()))
-                            .orElseGet(() -> new BlockPos(blockPos));
+                    BlockPos blockposition = this.ownerPlayer.blockPosition();
+                    BlockState iblockdata = this.cat.level().getBlockState(blockposition);
+
+                    if (iblockdata.is(BlockTags.BEDS)) {
+                        this.goalPos = (BlockPos) iblockdata.getOptionalValue(BedBlock.FACING).map((enumdirection) -> {
+                            return blockposition.relative(enumdirection.getOpposite());
+                        }).orElseGet(() -> {
+                            return new BlockPos(blockposition);
+                        });
                         return !this.spaceIsOccupied();
                     }
                 }
@@ -506,38 +557,44 @@
         }
 
         private boolean spaceIsOccupied() {
-            for (Cat cat : this.cat.level().getEntitiesOfClass(Cat.class, new AABB(this.goalPos).inflate(2.0))) {
-                if (cat != this.cat && (cat.isLying() || cat.isRelaxStateOne())) {
-                    return true;
-                }
-            }
+            List<Cat> list = this.cat.level().getEntitiesOfClass(Cat.class, (new AABB(this.goalPos)).inflate(2.0D));
+            Iterator iterator = list.iterator();
 
-            return false;
+            Cat entitycat;
+
+            do {
+                do {
+                    if (!iterator.hasNext()) {
+                        return false;
+                    }
+
+                    entitycat = (Cat) iterator.next();
+                } while (entitycat == this.cat);
+            } while (!entitycat.isLying() && !entitycat.isRelaxStateOne());
+
+            return true;
         }
 
         @Override
         public boolean canContinueToUse() {
-            return this.cat.isTame()
-                && !this.cat.isOrderedToSit()
-                && this.ownerPlayer != null
-                && this.ownerPlayer.isSleeping()
-                && this.goalPos != null
-                && !this.spaceIsOccupied();
+            return this.cat.isTame() && !this.cat.isOrderedToSit() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied();
         }
 
         @Override
         public void start() {
             if (this.goalPos != null) {
                 this.cat.setInSittingPose(false);
-                this.cat.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.1F);
+                this.cat.getNavigation().moveTo((double) this.goalPos.getX(), (double) this.goalPos.getY(), (double) this.goalPos.getZ(), 1.100000023841858D);
             }
+
         }
 
         @Override
         public void stop() {
             this.cat.setLying(false);
             float f = this.cat.level().getTimeOfDay(1.0F);
-            if (this.ownerPlayer.getSleepTimer() >= 100 && (double)f > 0.77 && (double)f < 0.8 && (double)this.cat.level().getRandom().nextFloat() < 0.7) {
+
+            if (this.ownerPlayer.getSleepTimer() >= 100 && (double) f > 0.77D && (double) f < 0.8D && (double) this.cat.level().getRandom().nextFloat() < 0.7D) {
                 this.giveMorningGift();
             }
 
@@ -547,45 +604,40 @@
         }
 
         private void giveMorningGift() {
-            RandomSource randomSource = this.cat.getRandom();
-            BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
-            mutableBlockPos.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition());
-            this.cat
-                .randomTeleport(
-                    (double)(mutableBlockPos.getX() + randomSource.nextInt(11) - 5),
-                    (double)(mutableBlockPos.getY() + randomSource.nextInt(5) - 2),
-                    (double)(mutableBlockPos.getZ() + randomSource.nextInt(11) - 5),
-                    false
-                );
-            mutableBlockPos.set(this.cat.blockPosition());
-            LootTable lootTable = this.cat.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT);
-            LootParams lootParams = new LootParams.Builder((ServerLevel)this.cat.level())
-                .withParameter(LootContextParams.ORIGIN, this.cat.position())
-                .withParameter(LootContextParams.THIS_ENTITY, this.cat)
-                .create(LootContextParamSets.GIFT);
+            RandomSource randomsource = this.cat.getRandom();
+            BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
 
-            for (ItemStack itemStack : lootTable.getRandomItems(lootParams)) {
-                this.cat
-                    .level()
-                    .addFreshEntity(
-                        new ItemEntity(
-                            this.cat.level(),
-                            (double)mutableBlockPos.getX() - (double)Mth.sin(this.cat.yBodyRot * (float) (Math.PI / 180.0)),
-                            (double)mutableBlockPos.getY(),
-                            (double)mutableBlockPos.getZ() + (double)Mth.cos(this.cat.yBodyRot * (float) (Math.PI / 180.0)),
-                            itemStack
-                        )
-                    );
+            blockposition_mutableblockposition.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition());
+            this.cat.randomTeleport((double) (blockposition_mutableblockposition.getX() + randomsource.nextInt(11) - 5), (double) (blockposition_mutableblockposition.getY() + randomsource.nextInt(5) - 2), (double) (blockposition_mutableblockposition.getZ() + randomsource.nextInt(11) - 5), false);
+            blockposition_mutableblockposition.set(this.cat.blockPosition());
+            LootTable loottable = this.cat.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT);
+            LootParams lootparams = (new LootParams.Builder((ServerLevel) this.cat.level())).withParameter(LootContextParams.ORIGIN, this.cat.position()).withParameter(LootContextParams.THIS_ENTITY, this.cat).create(LootContextParamSets.GIFT);
+            List<ItemStack> list = loottable.getRandomItems(lootparams);
+            Iterator iterator = list.iterator();
+
+            while (iterator.hasNext()) {
+                ItemStack itemstack = (ItemStack) iterator.next();
+
+                // CraftBukkit start
+                ItemEntity entityitem = new ItemEntity(this.cat.level(), (double) blockposition_mutableblockposition.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack);
+                org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
+                entityitem.level().getCraftServer().getPluginManager().callEvent(event);
+                if (event.isCancelled()) {
+                    continue;
+                }
+                this.cat.level().addFreshEntity(entityitem);
+                // CraftBukkit end
             }
+
         }
 
         @Override
         public void tick() {
             if (this.ownerPlayer != null && this.goalPos != null) {
                 this.cat.setInSittingPose(false);
-                this.cat.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.1F);
-                if (this.cat.distanceToSqr(this.ownerPlayer) < 2.5) {
-                    this.onBedTicks++;
+                this.cat.getNavigation().moveTo((double) this.goalPos.getX(), (double) this.goalPos.getY(), (double) this.goalPos.getZ(), 1.100000023841858D);
+                if (this.cat.distanceToSqr((Entity) this.ownerPlayer) < 2.5D) {
+                    ++this.onBedTicks;
                     if (this.onBedTicks > this.adjustedTickDelay(16)) {
                         this.cat.setLying(true);
                         this.cat.setRelaxStateOne(false);
@@ -597,37 +649,30 @@
                     this.cat.setLying(false);
                 }
             }
+
         }
     }
 
-    static class CatTemptGoal extends TemptGoal {
-        @Nullable
-        private Player selectedPlayer;
+    private static class CatAvoidEntityGoal<T extends LivingEntity> extends AvoidEntityGoal<T> {
+
         private final Cat cat;
 
-        public CatTemptGoal(Cat cat, double speed, Predicate<ItemStack> foodPredicate, boolean canBeScared) {
-            super(cat, speed, foodPredicate, canBeScared);
-            this.cat = cat;
-        }
+        public CatAvoidEntityGoal(Cat cat, Class<T> fleeFromType, float distance, double slowSpeed, double fastSpeed) {
+            // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error
 
-        @Override
-        public void tick() {
-            super.tick();
-            if (this.selectedPlayer == null && this.mob.getRandom().nextInt(this.adjustedTickDelay(600)) == 0) {
-                this.selectedPlayer = this.player;
-            } else if (this.mob.getRandom().nextInt(this.adjustedTickDelay(500)) == 0) {
-                this.selectedPlayer = null;
-            }
+            // Objects.requireNonNull(predicate); // CraftBukkit - decompile error
+            super(cat, fleeFromType, distance, slowSpeed, fastSpeed, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error
+            this.cat = cat;
         }
 
         @Override
-        protected boolean canScare() {
-            return (this.selectedPlayer == null || !this.selectedPlayer.equals(this.player)) && super.canScare();
+        public boolean canUse() {
+            return !this.cat.isTame() && super.canUse();
         }
 
         @Override
-        public boolean canUse() {
-            return super.canUse() && !this.cat.isTame();
+        public boolean canContinueToUse() {
+            return !this.cat.isTame() && super.canContinueToUse();
         }
     }
 }
