--- a/net/minecraft/world/item/BowItem.java
+++ b/net/minecraft/world/item/BowItem.java
@@ -14,6 +14,7 @@
 import net.minecraft.world.level.Level;
 
 public class BowItem extends ProjectileWeaponItem implements Vanishable {
+
     public static final int MAX_DRAW_DURATION = 20;
     public static final int DEFAULT_RANGE = 15;
 
@@ -23,66 +24,91 @@
 
     @Override
     public void releaseUsing(ItemStack stack, Level world, LivingEntity user, int remainingUseTicks) {
-        if (user instanceof Player player) {
-            boolean bl = player.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0;
-            ItemStack itemStack = player.getProjectile(stack);
-            if (!itemStack.isEmpty() || bl) {
-                if (itemStack.isEmpty()) {
-                    itemStack = new ItemStack(Items.ARROW);
+        if (user instanceof Player) {
+            Player entityhuman = (Player) user;
+            boolean flag = entityhuman.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0;
+            ItemStack itemstack1 = entityhuman.getProjectile(stack);
+
+            if (!itemstack1.isEmpty() || flag) {
+                if (itemstack1.isEmpty()) {
+                    itemstack1 = new ItemStack(Items.ARROW);
                 }
 
-                int i = this.getUseDuration(stack) - remainingUseTicks;
-                float f = getPowerForTime(i);
-                if (!((double)f < 0.1D)) {
-                    boolean bl2 = bl && itemStack.is(Items.ARROW);
+                int j = this.getUseDuration(stack) - remainingUseTicks;
+                float f = BowItem.getPowerForTime(j);
+
+                if ((double) f >= 0.1D) {
+                    boolean flag1 = flag && itemstack1.is(Items.ARROW);
+
                     if (!world.isClientSide) {
-                        ArrowItem arrowItem = (ArrowItem)(itemStack.getItem() instanceof ArrowItem ? itemStack.getItem() : Items.ARROW);
-                        AbstractArrow abstractArrow = arrowItem.createArrow(world, itemStack, player);
-                        abstractArrow.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, f * 3.0F, 1.0F);
+                        ArrowItem itemarrow = (ArrowItem) (itemstack1.getItem() instanceof ArrowItem ? itemstack1.getItem() : Items.ARROW);
+                        AbstractArrow entityarrow = itemarrow.createArrow(world, itemstack1, entityhuman);
+
+                        entityarrow.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, f * 3.0F, 1.0F);
                         if (f == 1.0F) {
-                            abstractArrow.setCritArrow(true);
+                            entityarrow.setCritArrow(true);
                         }
 
-                        int j = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, stack);
-                        if (j > 0) {
-                            abstractArrow.setBaseDamage(abstractArrow.getBaseDamage() + (double)j * 0.5D + 0.5D);
-                        }
+                        int k = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, stack);
 
-                        int k = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack);
                         if (k > 0) {
-                            abstractArrow.setKnockback(k);
+                            entityarrow.setBaseDamage(entityarrow.getBaseDamage() + (double) k * 0.5D + 0.5D);
+                        }
+
+                        int l = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack);
+
+                        if (l > 0) {
+                            entityarrow.setKnockback(l);
                         }
 
                         if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, stack) > 0) {
-                            abstractArrow.setSecondsOnFire(100);
+                            entityarrow.setSecondsOnFire(100);
                         }
+                        // CraftBukkit start
+                        org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.callEntityShootBowEvent(entityhuman, stack, itemstack1, entityarrow, entityhuman.getUsedItemHand(), f, !flag1);
+                        if (event.isCancelled()) {
+                            event.getProjectile().remove();
+                            return;
+                        }
+                        flag1 = !event.shouldConsumeItem();
+                        // CraftBukkit end
 
-                        stack.hurtAndBreak(1, player, (p) -> {
-                            p.broadcastBreakEvent(player.getUsedItemHand());
+                        stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> {
+                            entityhuman1.broadcastBreakEvent(entityhuman.getUsedItemHand());
                         });
-                        if (bl2 || player.getAbilities().instabuild && (itemStack.is(Items.SPECTRAL_ARROW) || itemStack.is(Items.TIPPED_ARROW))) {
-                            abstractArrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
+                        if (flag1 || entityhuman.getAbilities().instabuild && (itemstack1.is(Items.SPECTRAL_ARROW) || itemstack1.is(Items.TIPPED_ARROW))) {
+                            entityarrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
                         }
 
-                        world.addFreshEntity(abstractArrow);
+                        // CraftBukkit start
+                        if (event.getProjectile() == entityarrow.getBukkitEntity()) {
+                            if (!world.addFreshEntity(entityarrow)) {
+                                if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) {
+                                    ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory();
+                                }
+                                return;
+                            }
+                        }
+                        // CraftBukkit end
                     }
 
-                    world.playSound((Player)null, player.getX(), player.getY(), player.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (world.getRandom().nextFloat() * 0.4F + 1.2F) + f * 0.5F);
-                    if (!bl2 && !player.getAbilities().instabuild) {
-                        itemStack.shrink(1);
-                        if (itemStack.isEmpty()) {
-                            player.getInventory().removeItem(itemStack);
+                    world.playSound((Player) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (world.getRandom().nextFloat() * 0.4F + 1.2F) + f * 0.5F);
+                    if (!flag1 && !entityhuman.getAbilities().instabuild) {
+                        itemstack1.shrink(1);
+                        if (itemstack1.isEmpty()) {
+                            entityhuman.getInventory().removeItem(itemstack1);
                         }
                     }
 
-                    player.awardStat(Stats.ITEM_USED.get(this));
+                    entityhuman.awardStat(Stats.ITEM_USED.get(this));
                 }
             }
         }
     }
 
     public static float getPowerForTime(int useTicks) {
-        float f = (float)useTicks / 20.0F;
+        float f = (float) useTicks / 20.0F;
+
         f = (f * f + f * 2.0F) / 3.0F;
         if (f > 1.0F) {
             f = 1.0F;
@@ -103,19 +129,20 @@
 
     @Override
     public InteractionResultHolder<ItemStack> use(Level world, Player user, InteractionHand hand) {
-        ItemStack itemStack = user.getItemInHand(hand);
-        boolean bl = !user.getProjectile(itemStack).isEmpty();
-        if (!user.getAbilities().instabuild && !bl) {
-            return InteractionResultHolder.fail(itemStack);
+        ItemStack itemstack = user.getItemInHand(hand);
+        boolean flag = !user.getProjectile(itemstack).isEmpty();
+
+        if (!user.getAbilities().instabuild && !flag) {
+            return InteractionResultHolder.fail(itemstack);
         } else {
             user.startUsingItem(hand);
-            return InteractionResultHolder.consume(itemStack);
+            return InteractionResultHolder.consume(itemstack);
         }
     }
 
     @Override
     public Predicate<ItemStack> getAllSupportedProjectiles() {
-        return ARROW_ONLY;
+        return BowItem.ARROW_ONLY;
     }
 
     @Override
