--- a/net/minecraft/world/entity/animal/EntityAnimal.java
+++ b/net/minecraft/world/entity/animal/EntityAnimal.java
@@ -28,11 +28,18 @@
 import net.minecraft.world.level.gameevent.GameEvent;
 import net.minecraft.world.level.pathfinder.PathType;
 
+// CraftBukkit start
+import net.minecraft.world.entity.EntityTameableAnimal;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityEnterLoveModeEvent;
+// CraftBukkit end
+
 public abstract class EntityAnimal extends EntityAgeable {
 
     static final int PARENT_AGE_AFTER_BREEDING = 6000;
     public int inLove;
     public UUID loveCause;
+    public ItemStack breedItem; // CraftBukkit - Add breedItem variable
 
     protected EntityAnimal(EntityTypes<? extends EntityAnimal> entitytypes, World world) {
         super(entitytypes, world);
@@ -69,6 +76,9 @@
 
     }
 
+    /* CraftBukkit start
+    // Function disabled as it has no special function anymore after
+    // setSitting is disabled.
     @Override
     public boolean damageEntity(DamageSource damagesource, float f) {
         if (this.isInvulnerable(damagesource)) {
@@ -78,6 +88,7 @@
             return super.damageEntity(damagesource, f);
         }
     }
+    // CraftBukkit end */
 
     @Override
     public float a(BlockPosition blockposition, IWorldReader iworldreader) {
@@ -170,10 +181,17 @@
     }
 
     public void g(@Nullable EntityHuman entityhuman) {
-        this.inLove = 600;
+        // CraftBukkit start
+        EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(entityhuman, this, 600);
+        if (entityEnterLoveModeEvent.isCancelled()) {
+            return;
+        }
+        this.inLove = entityEnterLoveModeEvent.getTicksInLove();
+        // CraftBukkit end
         if (entityhuman != null) {
             this.loveCause = entityhuman.getUniqueID();
         }
+        this.breedItem = entityhuman.getInventory().getItemInHand(); // CraftBukkit
 
         this.level.broadcastEntityEffect(this, (byte) 18);
     }
@@ -213,11 +231,26 @@
         EntityAgeable entityageable = this.createChild(worldserver, entityanimal);
 
         if (entityageable != null) {
+            // CraftBukkit start - set persistence for tame animals
+            if (entityageable instanceof EntityTameableAnimal && ((EntityTameableAnimal) entityageable).isTamed()) {
+                entityageable.persistenceRequired = true;
+            }
+            // CraftBukkit end
             EntityPlayer entityplayer = this.getBreedCause();
 
             if (entityplayer == null && entityanimal.getBreedCause() != null) {
                 entityplayer = entityanimal.getBreedCause();
             }
+            // CraftBukkit start - call EntityBreedEvent
+            entityageable.setBaby(true);
+            entityageable.setPositionRotation(this.locX(), this.locY(), this.locZ(), 0.0F, 0.0F);
+            int experience = this.getRandom().nextInt(7) + 1;
+            org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, entityanimal, entityplayer, this.breedItem, experience);
+            if (entityBreedEvent.isCancelled()) {
+                return;
+            }
+            experience = entityBreedEvent.getExperience();
+            // CraftBukkit end
 
             if (entityplayer != null) {
                 entityplayer.a(StatisticList.ANIMALS_BRED);
@@ -228,12 +261,14 @@
             entityanimal.setAgeRaw(6000);
             this.resetLove();
             entityanimal.resetLove();
-            entityageable.setBaby(true);
-            entityageable.setPositionRotation(this.locX(), this.locY(), this.locZ(), 0.0F, 0.0F);
-            worldserver.addAllEntities(entityageable);
+            worldserver.addAllEntities(entityageable, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason
             worldserver.broadcastEntityEffect(this, (byte) 18);
             if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
-                worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), this.getRandom().nextInt(7) + 1));
+                // CraftBukkit start - use event experience
+                if (experience > 0) {
+                    worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience));
+                }
+                // CraftBukkit end
             }
 
         }
