--- a/net/minecraft/world/entity/monster/Bogged.java
+++ b/net/minecraft/world/entity/monster/Bogged.java
@@ -1,5 +1,6 @@
 package net.minecraft.world.entity.monster;
 
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
 import javax.annotation.Nullable;
 import net.minecraft.nbt.CompoundTag;
 import net.minecraft.network.syncher.EntityDataAccessor;
@@ -14,6 +15,7 @@
 import net.minecraft.world.damagesource.DamageSource;
 import net.minecraft.world.effect.MobEffectInstance;
 import net.minecraft.world.effect.MobEffects;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EntityType;
 import net.minecraft.world.entity.Shearable;
 import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
@@ -32,13 +34,14 @@
 import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
 
 public class Bogged extends AbstractSkeleton implements Shearable {
+
     private static final int HARD_ATTACK_INTERVAL = 50;
     private static final int NORMAL_ATTACK_INTERVAL = 70;
     private static final EntityDataAccessor<Boolean> DATA_SHEARED = SynchedEntityData.defineId(Bogged.class, EntityDataSerializers.BOOLEAN);
     public static final String SHEARED_TAG_NAME = "sheared";
 
     public static AttributeSupplier.Builder createAttributes() {
-        return AbstractSkeleton.createAttributes().add(Attributes.MAX_HEALTH, 16.0);
+        return AbstractSkeleton.createAttributes().add(Attributes.MAX_HEALTH, 16.0D);
     }
 
     public Bogged(EntityType<? extends Bogged> type, Level world) {
@@ -48,7 +51,7 @@
     @Override
     protected void defineSynchedData(SynchedEntityData.Builder builder) {
         super.defineSynchedData(builder);
-        builder.define(DATA_SHEARED, false);
+        builder.define(Bogged.DATA_SHEARED, false);
     }
 
     @Override
@@ -64,21 +67,35 @@
     }
 
     public boolean isSheared() {
-        return this.entityData.get(DATA_SHEARED);
+        return (Boolean) this.entityData.get(Bogged.DATA_SHEARED);
     }
 
     public void setSheared(boolean sheared) {
-        this.entityData.set(DATA_SHEARED, sheared);
+        this.entityData.set(Bogged.DATA_SHEARED, sheared);
     }
 
     @Override
     protected InteractionResult mobInteract(Player player, InteractionHand hand) {
-        ItemStack itemStack = player.getItemInHand(hand);
-        if (itemStack.is(Items.SHEARS) && this.readyForShearing()) {
-            this.shear(SoundSource.PLAYERS);
+        ItemStack itemstack = player.getItemInHand(hand);
+
+        if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
+            // CraftBukkit start
+            // Paper start - expose drops in event
+            java.util.List<net.minecraft.world.item.ItemStack> drops = generateDefaultDrops();
+            final org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
+            if (event != null) {
+                if (event.isCancelled()) {
+                    if (player instanceof final net.minecraft.server.level.ServerPlayer serverPlayer) this.resendPossiblyDesyncedDataValues(java.util.List.of(Bogged.DATA_SHEARED), serverPlayer);
+                    return InteractionResult.PASS;
+                }
+                drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
+            // Paper end - expose drops in event
+            }
+            // CraftBukkit end
+            this.shear(SoundSource.PLAYERS, drops); // Paper - expose drops in event
             this.gameEvent(GameEvent.SHEAR, player);
             if (!this.level().isClientSide) {
-                itemStack.hurtAndBreak(1, player, getSlotForHand(hand));
+                itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
             }
 
             return InteractionResult.sidedSuccess(this.level().isClientSide);
@@ -109,12 +126,13 @@
 
     @Override
     protected AbstractArrow getArrow(ItemStack arrow, float damageModifier, @Nullable ItemStack shotFrom) {
-        AbstractArrow abstractArrow = super.getArrow(arrow, damageModifier, shotFrom);
-        if (abstractArrow instanceof Arrow arrow2) {
-            arrow2.addEffect(new MobEffectInstance(MobEffects.POISON, 100));
+        AbstractArrow entityarrow = super.getArrow(arrow, damageModifier, shotFrom);
+
+        if (entityarrow instanceof Arrow entitytippedarrow) {
+            entitytippedarrow.addEffect(new MobEffectInstance(MobEffects.POISON, 100));
         }
 
-        return abstractArrow;
+        return entityarrow;
     }
 
     @Override
@@ -129,25 +147,56 @@
 
     @Override
     public void shear(SoundSource shearedSoundCategory) {
-        this.level().playSound(null, this, SoundEvents.BOGGED_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
-        this.spawnShearedMushrooms();
+    // Paper start - shear drop API
+        this.shear(shearedSoundCategory, generateDefaultDrops());
+    }
+
+    @Override
+    public void shear(SoundSource shearedSoundCategory, java.util.List<net.minecraft.world.item.ItemStack> drops) {
+    // Paper end - shear drop API
+        this.level().playSound((Player) null, (Entity) this, SoundEvents.BOGGED_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
+        this.spawnDrops(drops); // Paper - shear drop API
         this.setSheared(true);
     }
 
     private void spawnShearedMushrooms() {
-        if (this.level() instanceof ServerLevel serverLevel) {
-            LootTable lootTable = serverLevel.getServer().reloadableRegistries().getLootTable(BuiltInLootTables.BOGGED_SHEAR);
-            LootParams lootParams = new LootParams.Builder(serverLevel)
-                .withParameter(LootContextParams.ORIGIN, this.position())
-                .withParameter(LootContextParams.THIS_ENTITY, this)
-                .create(LootContextParamSets.SHEARING);
+    // Paper start - shear drops API
+        this.spawnDrops(generateDefaultDrops()); // Only here for people calling spawnSheardMushrooms. Not used otherwise.
+    }
+    private void spawnDrops(java.util.List<net.minecraft.world.item.ItemStack> drops) {
+        drops.forEach(stack -> {
+            this.forceDrops = true;
+            this.spawnAtLocation(stack, this.getBbHeight());
+            this.forceDrops = false;
+        });
+    }
+    private void generateShearedMushrooms(java.util.function.Consumer<ItemStack> stackConsumer) {
+    // Paper end - shear drops API
+        Level world = this.level();
 
-            for (ItemStack itemStack : lootTable.getRandomItems(lootParams)) {
-                this.spawnAtLocation(itemStack, this.getBbHeight());
+        if (world instanceof ServerLevel worldserver) {
+            LootTable loottable = worldserver.getServer().reloadableRegistries().getLootTable(BuiltInLootTables.BOGGED_SHEAR);
+            LootParams lootparams = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.THIS_ENTITY, this).create(LootContextParamSets.SHEARING);
+            ObjectListIterator objectlistiterator = loottable.getRandomItems(lootparams).iterator();
+
+            while (objectlistiterator.hasNext()) {
+                ItemStack itemstack = (ItemStack) objectlistiterator.next();
+
+                stackConsumer.accept(itemstack); // Paper
             }
         }
+
     }
 
+    // Paper start - shear drops API
+    @Override
+    public java.util.List<ItemStack> generateDefaultDrops() {
+        final java.util.List<ItemStack> drops = new java.util.ArrayList<>();
+        this.generateShearedMushrooms(drops::add);
+        return drops;
+    }
+    // Paper end - shear drops API
+
     @Override
     public boolean readyForShearing() {
         return !this.isSheared() && this.isAlive();
