--- a/net/minecraft/world/entity/animal/MushroomCow.java
+++ b/net/minecraft/world/entity/animal/MushroomCow.java
@@ -20,6 +20,7 @@
 import net.minecraft.world.InteractionResult;
 import net.minecraft.world.effect.MobEffect;
 import net.minecraft.world.entity.AgeableMob;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EntityType;
 import net.minecraft.world.entity.LightningBolt;
 import net.minecraft.world.entity.MobSpawnType;
@@ -42,7 +43,15 @@
 import net.minecraft.world.level.gameevent.GameEvent;
 import org.apache.commons.lang3.tuple.Pair;
 
+// CraftBukkit start
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_19_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityDropItemEvent;
+import org.bukkit.event.entity.EntityTransformEvent;
+// CraftBukkit end
+
 public class MushroomCow extends Cow implements Shearable {
+
     private static final EntityDataAccessor<String> DATA_TYPE = SynchedEntityData.defineId(MushroomCow.class, EntityDataSerializers.STRING);
     private static final int MUTATE_CHANCE = 1024;
     @Nullable
@@ -66,10 +75,11 @@
 
     @Override
     public void thunderHit(ServerLevel world, LightningBolt lightning) {
-        UUID uUID = lightning.getUUID();
-        if (!uUID.equals(this.lastLightningBoltUUID)) {
+        UUID uuid = lightning.getUUID();
+
+        if (!uuid.equals(this.lastLightningBoltUUID)) {
             this.setMushroomType(this.getMushroomType() == MushroomCow.MushroomType.RED ? MushroomCow.MushroomType.BROWN : MushroomCow.MushroomType.RED);
-            this.lastLightningBoltUUID = uUID;
+            this.lastLightningBoltUUID = uuid;
             this.playSound(SoundEvents.MOOSHROOM_CONVERT, 2.0F, 1.0F);
         }
 
@@ -78,68 +88,79 @@
     @Override
     protected void defineSynchedData() {
         super.defineSynchedData();
-        this.entityData.define(DATA_TYPE, MushroomCow.MushroomType.RED.type);
+        this.entityData.define(MushroomCow.DATA_TYPE, MushroomCow.MushroomType.RED.type);
     }
 
     @Override
     public InteractionResult mobInteract(Player player, InteractionHand hand) {
-        ItemStack itemStack = player.getItemInHand(hand);
-        if (itemStack.is(Items.BOWL) && !this.isBaby()) {
-            boolean bl = false;
-            ItemStack itemStack2;
+        ItemStack itemstack = player.getItemInHand(hand);
+
+        if (itemstack.is(Items.BOWL) && !this.isBaby()) {
+            boolean flag = false;
+            ItemStack itemstack1;
+
             if (this.effect != null) {
-                bl = true;
-                itemStack2 = new ItemStack(Items.SUSPICIOUS_STEW);
-                SuspiciousStewItem.saveMobEffect(itemStack2, this.effect, this.effectDuration);
+                flag = true;
+                itemstack1 = new ItemStack(Items.SUSPICIOUS_STEW);
+                SuspiciousStewItem.saveMobEffect(itemstack1, this.effect, this.effectDuration);
                 this.effect = null;
                 this.effectDuration = 0;
             } else {
-                itemStack2 = new ItemStack(Items.MUSHROOM_STEW);
+                itemstack1 = new ItemStack(Items.MUSHROOM_STEW);
             }
 
-            ItemStack itemStack4 = ItemUtils.createFilledResult(itemStack, player, itemStack2, false);
-            player.setItemInHand(hand, itemStack4);
-            SoundEvent soundEvent;
-            if (bl) {
-                soundEvent = SoundEvents.MOOSHROOM_MILK_SUSPICIOUSLY;
+            ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false);
+
+            player.setItemInHand(hand, itemstack2);
+            SoundEvent soundeffect;
+
+            if (flag) {
+                soundeffect = SoundEvents.MOOSHROOM_MILK_SUSPICIOUSLY;
             } else {
-                soundEvent = SoundEvents.MOOSHROOM_MILK;
+                soundeffect = SoundEvents.MOOSHROOM_MILK;
             }
 
-            this.playSound(soundEvent, 1.0F, 1.0F);
+            this.playSound(soundeffect, 1.0F, 1.0F);
             return InteractionResult.sidedSuccess(this.level.isClientSide);
-        } else if (itemStack.is(Items.SHEARS) && this.readyForShearing()) {
+        } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
+            // CraftBukkit start
+            if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) {
+                return InteractionResult.PASS;
+            }
+            // CraftBukkit end
             this.shear(SoundSource.PLAYERS);
             this.gameEvent(GameEvent.SHEAR, player);
             if (!this.level.isClientSide) {
-                itemStack.hurtAndBreak(1, player, (playerx) -> {
-                    playerx.broadcastBreakEvent(hand);
+                itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
+                    entityhuman1.broadcastBreakEvent(hand);
                 });
             }
 
             return InteractionResult.sidedSuccess(this.level.isClientSide);
-        } else if (this.getMushroomType() == MushroomCow.MushroomType.BROWN && itemStack.is(ItemTags.SMALL_FLOWERS)) {
+        } else if (this.getMushroomType() == MushroomCow.MushroomType.BROWN && itemstack.is(ItemTags.SMALL_FLOWERS)) {
             if (this.effect != null) {
-                for(int i = 0; i < 2; ++i) {
+                for (int i = 0; i < 2; ++i) {
                     this.level.addParticle(ParticleTypes.SMOKE, this.getX() + this.random.nextDouble() / 2.0D, this.getY(0.5D), this.getZ() + this.random.nextDouble() / 2.0D, 0.0D, this.random.nextDouble() / 5.0D, 0.0D);
                 }
             } else {
-                Optional<Pair<MobEffect, Integer>> optional = this.getEffectFromItemStack(itemStack);
+                Optional<Pair<MobEffect, Integer>> optional = this.getEffectFromItemStack(itemstack);
+
                 if (!optional.isPresent()) {
                     return InteractionResult.PASS;
                 }
 
-                Pair<MobEffect, Integer> pair = optional.get();
+                Pair<MobEffect, Integer> pair = (Pair) optional.get();
+
                 if (!player.getAbilities().instabuild) {
-                    itemStack.shrink(1);
+                    itemstack.shrink(1);
                 }
 
-                for(int j = 0; j < 4; ++j) {
+                for (int j = 0; j < 4; ++j) {
                     this.level.addParticle(ParticleTypes.EFFECT, this.getX() + this.random.nextDouble() / 2.0D, this.getY(0.5D), this.getZ() + this.random.nextDouble() / 2.0D, 0.0D, this.random.nextDouble() / 5.0D, 0.0D);
                 }
 
-                this.effect = pair.getLeft();
-                this.effectDuration = pair.getRight();
+                this.effect = (MobEffect) pair.getLeft();
+                this.effectDuration = (Integer) pair.getRight();
                 this.playSound(SoundEvents.MOOSHROOM_EAT, 2.0F, 1.0F);
             }
 
@@ -151,28 +172,44 @@
 
     @Override
     public void shear(SoundSource shearedSoundCategory) {
-        this.level.playSound((Player)null, this, SoundEvents.MOOSHROOM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
+        this.level.playSound((Player) null, (Entity) this, SoundEvents.MOOSHROOM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
         if (!this.level.isClientSide()) {
-            ((ServerLevel)this.level).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D);
-            this.discard();
-            Cow cow = EntityType.COW.create(this.level);
-            cow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
-            cow.setHealth(this.getHealth());
-            cow.yBodyRot = this.yBodyRot;
+            ((ServerLevel) this.level).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D);
+            // this.discard(); // CraftBukkit - moved down
+            Cow entitycow = (Cow) EntityType.COW.create(this.level);
+
+            entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
+            entitycow.setHealth(this.getHealth());
+            entitycow.yBodyRot = this.yBodyRot;
             if (this.hasCustomName()) {
-                cow.setCustomName(this.getCustomName());
-                cow.setCustomNameVisible(this.isCustomNameVisible());
+                entitycow.setCustomName(this.getCustomName());
+                entitycow.setCustomNameVisible(this.isCustomNameVisible());
             }
 
             if (this.isPersistenceRequired()) {
-                cow.setPersistenceRequired();
+                entitycow.setPersistenceRequired();
             }
 
-            cow.setInvulnerable(this.isInvulnerable());
-            this.level.addFreshEntity(cow);
+            entitycow.setInvulnerable(this.isInvulnerable());
+            // CraftBukkit start
+            if (CraftEventFactory.callEntityTransformEvent(this, entitycow, EntityTransformEvent.TransformReason.SHEARED).isCancelled()) {
+                return;
+            }
+            this.level.addFreshEntity(entitycow, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED);
 
-            for(int i = 0; i < 5; ++i) {
-                this.level.addFreshEntity(new ItemEntity(this.level, this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getMushroomType().blockState.getBlock())));
+            this.discard(); // CraftBukkit - from above
+            // CraftBukkit end
+
+            for (int i = 0; i < 5; ++i) {
+                // CraftBukkit start
+                ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getMushroomType().blockState.getBlock()));
+                EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
+                Bukkit.getPluginManager().callEvent(event);
+                if (event.isCancelled()) {
+                    continue;
+                }
+                this.level.addFreshEntity(entityitem);
+                // CraftBukkit end
             }
         }
 
@@ -210,11 +247,14 @@
 
     private Optional<Pair<MobEffect, Integer>> getEffectFromItemStack(ItemStack flower) {
         Item item = flower.getItem();
+
         if (item instanceof BlockItem) {
-            Block block = ((BlockItem)item).getBlock();
+            Block block = ((BlockItem) item).getBlock();
+
             if (block instanceof FlowerBlock) {
-                FlowerBlock flowerBlock = (FlowerBlock)block;
-                return Optional.of(Pair.of(flowerBlock.getSuspiciousStewEffect(), flowerBlock.getEffectDuration()));
+                FlowerBlock blockflowers = (FlowerBlock) block;
+
+                return Optional.of(Pair.of(blockflowers.getSuspiciousStewEffect(), blockflowers.getEffectDuration()));
             }
         }
 
@@ -222,43 +262,45 @@
     }
 
     public void setMushroomType(MushroomCow.MushroomType type) {
-        this.entityData.set(DATA_TYPE, type.type);
+        this.entityData.set(MushroomCow.DATA_TYPE, type.type);
     }
 
     public MushroomCow.MushroomType getMushroomType() {
-        return MushroomCow.MushroomType.byType(this.entityData.get(DATA_TYPE));
+        return MushroomCow.MushroomType.byType((String) this.entityData.get(MushroomCow.DATA_TYPE));
     }
 
     @Override
-    public MushroomCow getBreedOffspring(ServerLevel serverLevel, AgeableMob ageableMob) {
-        MushroomCow mushroomCow = EntityType.MOOSHROOM.create(serverLevel);
-        mushroomCow.setMushroomType(this.getOffspringType((MushroomCow)ageableMob));
-        return mushroomCow;
+    public MushroomCow getBreedOffspring(ServerLevel world, AgeableMob entity) {
+        MushroomCow entitymushroomcow = (MushroomCow) EntityType.MOOSHROOM.create(world);
+
+        entitymushroomcow.setMushroomType(this.getOffspringType((MushroomCow) entity));
+        return entitymushroomcow;
     }
 
     private MushroomCow.MushroomType getOffspringType(MushroomCow mooshroom) {
-        MushroomCow.MushroomType mushroomType = this.getMushroomType();
-        MushroomCow.MushroomType mushroomType2 = mooshroom.getMushroomType();
-        MushroomCow.MushroomType mushroomType3;
-        if (mushroomType == mushroomType2 && this.random.nextInt(1024) == 0) {
-            mushroomType3 = mushroomType == MushroomCow.MushroomType.BROWN ? MushroomCow.MushroomType.RED : MushroomCow.MushroomType.BROWN;
+        MushroomCow.MushroomType entitymushroomcow_type = this.getMushroomType();
+        MushroomCow.MushroomType entitymushroomcow_type1 = mooshroom.getMushroomType();
+        MushroomCow.MushroomType entitymushroomcow_type2;
+
+        if (entitymushroomcow_type == entitymushroomcow_type1 && this.random.nextInt(1024) == 0) {
+            entitymushroomcow_type2 = entitymushroomcow_type == MushroomCow.MushroomType.BROWN ? MushroomCow.MushroomType.RED : MushroomCow.MushroomType.BROWN;
         } else {
-            mushroomType3 = this.random.nextBoolean() ? mushroomType : mushroomType2;
+            entitymushroomcow_type2 = this.random.nextBoolean() ? entitymushroomcow_type : entitymushroomcow_type1;
         }
 
-        return mushroomType3;
+        return entitymushroomcow_type2;
     }
 
     public static enum MushroomType {
-        RED("red", Blocks.RED_MUSHROOM.defaultBlockState()),
-        BROWN("brown", Blocks.BROWN_MUSHROOM.defaultBlockState());
+
+        RED("red", Blocks.RED_MUSHROOM.defaultBlockState()), BROWN("brown", Blocks.BROWN_MUSHROOM.defaultBlockState());
 
         final String type;
         final BlockState blockState;
 
-        private MushroomType(String name, BlockState mushroom) {
-            this.type = name;
-            this.blockState = mushroom;
+        private MushroomType(String s, BlockState iblockdata) {
+            this.type = s;
+            this.blockState = iblockdata;
         }
 
         public BlockState getBlockState() {
@@ -266,13 +308,18 @@
         }
 
         static MushroomCow.MushroomType byType(String name) {
-            for(MushroomCow.MushroomType mushroomType : values()) {
-                if (mushroomType.type.equals(name)) {
-                    return mushroomType;
+            MushroomCow.MushroomType[] aentitymushroomcow_type = values();
+            int i = aentitymushroomcow_type.length;
+
+            for (int j = 0; j < i; ++j) {
+                MushroomCow.MushroomType entitymushroomcow_type = aentitymushroomcow_type[j];
+
+                if (entitymushroomcow_type.type.equals(name)) {
+                    return entitymushroomcow_type;
                 }
             }
 
-            return RED;
+            return MushroomCow.MushroomType.RED;
         }
     }
 }
