--- a/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
@@ -88,8 +_,8 @@
     public static final double GOAT_SCREAMING_CHANCE = 0.02;
     public static final double UNIHORN_CHANCE = 0.1F;
     private static final EntityDataAccessor<Boolean> DATA_IS_SCREAMING_GOAT = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN);
-    private static final EntityDataAccessor<Boolean> DATA_HAS_LEFT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN);
-    private static final EntityDataAccessor<Boolean> DATA_HAS_RIGHT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN);
+    public static final EntityDataAccessor<Boolean> DATA_HAS_LEFT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN);
+    public static final EntityDataAccessor<Boolean> DATA_HAS_RIGHT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN);
     private static final boolean DEFAULT_IS_SCREAMING = false;
     private static final boolean DEFAULT_HAS_LEFT_HORN = true;
     private static final boolean DEFAULT_HAS_RIGHT_HORN = true;
@@ -145,17 +_,17 @@
     }
 
     @Override
-    protected SoundEvent getAmbientSound() {
+    public SoundEvent getAmbientSound() {
         return this.isScreamingGoat() ? SoundEvents.GOAT_SCREAMING_AMBIENT : SoundEvents.GOAT_AMBIENT;
     }
 
     @Override
-    protected SoundEvent getHurtSound(DamageSource damageSource) {
+    public SoundEvent getHurtSound(DamageSource damageSource) {
         return this.isScreamingGoat() ? SoundEvents.GOAT_SCREAMING_HURT : SoundEvents.GOAT_HURT;
     }
 
     @Override
-    protected SoundEvent getDeathSound() {
+    public SoundEvent getDeathSound() {
         return this.isScreamingGoat() ? SoundEvents.GOAT_SCREAMING_DEATH : SoundEvents.GOAT_DEATH;
     }
 
@@ -234,13 +_,22 @@
     public InteractionResult mobInteract(Player player, InteractionHand hand) {
         ItemStack itemInHand = player.getItemInHand(hand);
         if (itemInHand.is(Items.BUCKET) && !this.isBaby()) {
+            // CraftBukkit start - Got milk?
+            org.bukkit.event.player.PlayerBucketFillEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(player.level(), player, this.blockPosition(), this.blockPosition(), null, itemInHand, Items.MILK_BUCKET, hand);
+
+            if (event.isCancelled()) {
+                player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
+                return InteractionResult.PASS;
+            }
+            // CraftBukkit end
             player.playSound(this.getMilkingSound(), 1.0F, 1.0F);
-            ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, Items.MILK_BUCKET.getDefaultInstance());
+            ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
             player.setItemInHand(hand, itemStack);
             return InteractionResult.SUCCESS;
         } else {
+            boolean isFood = this.isFood(itemInHand); // Paper - track before stack is possibly decreased to 0 (Fixes MC-244739)
             InteractionResult interactionResult = super.mobInteract(player, hand);
-            if (interactionResult.consumesAction() && this.isFood(itemInHand)) {
+            if (interactionResult.consumesAction() && isFood) { // Paper
                 this.playEatingSound();
             }
 
@@ -352,8 +_,7 @@
             double d1 = Mth.randomBetween(this.random, 0.3F, 0.7F);
             double d2 = Mth.randomBetween(this.random, -0.2F, 0.2F);
             ItemEntity itemEntity = new ItemEntity(this.level(), vec3.x(), vec3.y(), vec3.z(), itemStack, d, d1, d2);
-            this.level().addFreshEntity(itemEntity);
-            return true;
+            return this.spawnAtLocation((net.minecraft.server.level.ServerLevel) this.level(), itemEntity) != null; // Paper - Call EntityDropItemEvent
         }
     }
 
@@ -384,4 +_,15 @@
     ) {
         return level.getBlockState(pos.below()).is(BlockTags.GOATS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos);
     }
+
+    // Paper start - Goat ram API
+    public void ram(net.minecraft.world.entity.LivingEntity entity) {
+        Brain<Goat> brain = this.getBrain();
+        brain.setMemory(MemoryModuleType.RAM_TARGET, entity.position());
+        brain.eraseMemory(MemoryModuleType.RAM_COOLDOWN_TICKS);
+        brain.eraseMemory(MemoryModuleType.BREED_TARGET);
+        brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER);
+        brain.setActiveActivityIfPossible(net.minecraft.world.entity.schedule.Activity.RAM);
+    }
+    // Paper end - Goat ram API
 }
