--- a/net/minecraft/world/entity/animal/Cat.java
+++ b/net/minecraft/world/entity/animal/Cat.java
@@ -373,6 +_,11 @@
                 if (item instanceof DyeItem dyeItem) {
                     DyeColor dyeColor = dyeItem.getDyeColor();
                     if (dyeColor != 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) dyeColor.getId()), ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity());
+                        if (!event.callEvent()) return InteractionResult.FAIL;
+                        dyeColor = DyeColor.byId(event.getColor().getWoolData());
+                        // Paper end - Add EntityDyeEvent and CollarColorable interface
                         if (!this.level().isClientSide()) {
                             this.setCollarColor(dyeColor);
                             itemInHand.consume(1, player);
@@ -385,7 +_,7 @@
                     if (!this.level().isClientSide()) {
                         this.usePlayerItem(player, hand, itemInHand);
                         FoodProperties foodProperties = itemInHand.get(DataComponents.FOOD);
-                        this.heal(foodProperties != null ? foodProperties.nutrition() : 1.0F);
+                        this.heal(foodProperties != null ? foodProperties.nutrition() : 1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // Paper - Add missing regain reason
                         this.playEatingSound();
                     }
 
@@ -447,7 +_,7 @@
     }
 
     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);
@@ -581,15 +_,20 @@
                 .dropFromGiftLootTable(
                     getServerLevel(this.cat),
                     BuiltInLootTables.CAT_MORNING_GIFT,
-                    (level, stack) -> level.addFreshEntity(
-                        new ItemEntity(
+                    // CraftBukkit start
+                    (level, stack) -> {
+                        final ItemEntity item = new ItemEntity(
                             level,
                             (double)mutableBlockPos.getX() - Mth.sin(this.cat.yBodyRot * (float) (Math.PI / 180.0)),
                             mutableBlockPos.getY(),
                             (double)mutableBlockPos.getZ() + Mth.cos(this.cat.yBodyRot * (float) (Math.PI / 180.0)),
                             stack
-                        )
-                    )
+                        );
+                        org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) item.getBukkitEntity());
+                        if (!event.callEvent()) return;
+                        level.addFreshEntity(item);
+                    }
+                    // CraftBukkit end
                 );
         }
 
@@ -616,7 +_,7 @@
 
     static class CatTemptGoal extends TemptGoal {
         @Nullable
-        private Player selectedPlayer;
+        private LivingEntity selectedPlayer; // CraftBukkit
         private final Cat cat;
 
         public CatTemptGoal(Cat cat, double speedModifier, Predicate<ItemStack> items, boolean canScare) {
