--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
@@ -31,7 +31,14 @@
 import net.minecraft.world.phys.Vec3;
 import org.slf4j.Logger;
 
+// CraftBukkit start
+import java.util.Arrays;
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
+
 public class BrushableBlockEntity extends BlockEntity {
+
     private static final Logger LOGGER = LogUtils.getLogger();
     private static final String LOOT_TABLE_TAG = "LootTable";
     private static final String LOOT_TABLE_SEED_TAG = "LootTableSeed";
@@ -43,7 +50,7 @@
     private int brushCount;
     private long brushCountResetsAtTick;
     private long coolDownEndsAtTick;
-    public ItemStack item = ItemStack.EMPTY;
+    public ItemStack item;
     @Nullable
     private Direction hitDirection;
     @Nullable
@@ -52,6 +59,7 @@
 
     public BrushableBlockEntity(BlockPos pos, BlockState state) {
         super(BlockEntityType.BRUSHABLE_BLOCK, pos, state);
+        this.item = ItemStack.EMPTY;
     }
 
     public boolean brush(long worldTime, Player player, Direction hitDirection) {
@@ -63,17 +71,20 @@
         if (worldTime >= this.coolDownEndsAtTick && this.level instanceof ServerLevel) {
             this.coolDownEndsAtTick = worldTime + 10L;
             this.unpackLootTable(player);
-            int i = this.getCompletionState();
+            int j = this.getCompletionState();
+
             if (++this.brushCount >= 10) {
                 this.brushingCompleted(player);
                 return true;
             } else {
                 this.level.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), 2);
-                int j = this.getCompletionState();
-                if (i != j) {
-                    BlockState blockState = this.getBlockState();
-                    BlockState blockState2 = blockState.setValue(BlockStateProperties.DUSTED, Integer.valueOf(j));
-                    this.level.setBlock(this.getBlockPos(), blockState2, 3);
+                int k = this.getCompletionState();
+
+                if (j != k) {
+                    BlockState iblockdata = this.getBlockState();
+                    BlockState iblockdata1 = (BlockState) iblockdata.setValue(BlockStateProperties.DUSTED, k);
+
+                    this.level.setBlock(this.getBlockPos(), iblockdata1, 3);
                 }
 
                 return false;
@@ -85,26 +96,31 @@
 
     public void unpackLootTable(Player player) {
         if (this.lootTable != null && this.level != null && !this.level.isClientSide() && this.level.getServer() != null) {
-            LootTable lootTable = this.level.getServer().reloadableRegistries().getLootTable(this.lootTable);
-            if (player instanceof ServerPlayer serverPlayer) {
-                CriteriaTriggers.GENERATE_LOOT.trigger(serverPlayer, this.lootTable);
+            LootTable loottable = this.level.getServer().reloadableRegistries().getLootTable(this.lootTable);
+
+            if (player instanceof ServerPlayer) {
+                ServerPlayer entityplayer = (ServerPlayer) player;
+
+                CriteriaTriggers.GENERATE_LOOT.trigger(entityplayer, this.lootTable);
             }
 
-            LootParams lootParams = new LootParams.Builder((ServerLevel)this.level)
-                .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition))
-                .withLuck(player.getLuck())
-                .withParameter(LootContextParams.THIS_ENTITY, player)
-                .create(LootContextParamSets.CHEST);
-            ObjectArrayList<ItemStack> objectArrayList = lootTable.getRandomItems(lootParams, this.lootTableSeed);
+            LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)).withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player).create(LootContextParamSets.CHEST);
+            ObjectArrayList<ItemStack> objectarraylist = loottable.getRandomItems(lootparams, this.lootTableSeed);
+            ItemStack itemstack;
 
-            this.item = switch (objectArrayList.size()) {
-                case 0 -> ItemStack.EMPTY;
-                case 1 -> (ItemStack)objectArrayList.get(0);
-                default -> {
-                    LOGGER.warn("Expected max 1 loot from loot table {}, but got {}", this.lootTable.location(), objectArrayList.size());
-                    yield objectArrayList.get(0);
-                }
-            };
+            switch (objectarraylist.size()) {
+                case 0:
+                    itemstack = ItemStack.EMPTY;
+                    break;
+                case 1:
+                    itemstack = (ItemStack) objectarraylist.get(0);
+                    break;
+                default:
+                    BrushableBlockEntity.LOGGER.warn("Expected max 1 loot from loot table {}, but got {}", this.lootTable.location(), objectarraylist.size());
+                    itemstack = (ItemStack) objectarraylist.get(0);
+            }
+
+            this.item = itemstack;
             this.lootTable = null;
             this.setChanged();
         }
@@ -113,16 +129,21 @@
     private void brushingCompleted(Player player) {
         if (this.level != null && this.level.getServer() != null) {
             this.dropContent(player);
-            BlockState blockState = this.getBlockState();
-            this.level.levelEvent(3008, this.getBlockPos(), Block.getId(blockState));
-            Block block2;
-            if (this.getBlockState().getBlock() instanceof BrushableBlock brushableBlock) {
-                block2 = brushableBlock.getTurnsInto();
+            BlockState iblockdata = this.getBlockState();
+
+            this.level.levelEvent(3008, this.getBlockPos(), Block.getId(iblockdata));
+            Block block = this.getBlockState().getBlock();
+            Block block1;
+
+            if (block instanceof BrushableBlock) {
+                BrushableBlock brushableblock = (BrushableBlock) block;
+
+                block1 = brushableblock.getTurnsInto();
             } else {
-                block2 = Blocks.AIR;
+                block1 = Blocks.AIR;
             }
 
-            this.level.setBlock(this.worldPosition, block2.defaultBlockState(), 3);
+            this.level.setBlock(this.worldPosition, block1.defaultBlockState(), 3);
         }
     }
 
@@ -130,19 +151,24 @@
         if (this.level != null && this.level.getServer() != null) {
             this.unpackLootTable(player);
             if (!this.item.isEmpty()) {
-                double d = (double)EntityType.ITEM.getWidth();
-                double e = 1.0 - d;
-                double f = d / 2.0;
-                Direction direction = Objects.requireNonNullElse(this.hitDirection, Direction.UP);
-                BlockPos blockPos = this.worldPosition.relative(direction, 1);
-                double g = (double)blockPos.getX() + 0.5 * e + f;
-                double h = (double)blockPos.getY() + 0.5 + (double)(EntityType.ITEM.getHeight() / 2.0F);
-                double i = (double)blockPos.getZ() + 0.5 * e + f;
-                ItemEntity itemEntity = new ItemEntity(this.level, g, h, i, this.item.split(this.level.random.nextInt(21) + 10));
-                itemEntity.setDeltaMovement(Vec3.ZERO);
-                this.level.addFreshEntity(itemEntity);
+                double d0 = (double) EntityType.ITEM.getWidth();
+                double d1 = 1.0D - d0;
+                double d2 = d0 / 2.0D;
+                Direction enumdirection = (Direction) Objects.requireNonNullElse(this.hitDirection, Direction.UP);
+                BlockPos blockposition = this.worldPosition.relative(enumdirection, 1);
+                double d3 = (double) blockposition.getX() + 0.5D * d1 + d2;
+                double d4 = (double) blockposition.getY() + 0.5D + (double) (EntityType.ITEM.getHeight() / 2.0F);
+                double d5 = (double) blockposition.getZ() + 0.5D * d1 + d2;
+                ItemEntity entityitem = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10));
+
+                entityitem.setDeltaMovement(Vec3.ZERO);
+                // CraftBukkit start
+                org.bukkit.block.Block bblock = CraftBlock.at(this.level, this.worldPosition);
+                CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (ServerPlayer) player, Arrays.asList(entityitem));
+                // CraftBukkit end
                 this.item = ItemStack.EMPTY;
             }
+
         }
     }
 
@@ -150,13 +176,16 @@
         if (this.level != null) {
             if (this.brushCount != 0 && this.level.getGameTime() >= this.brushCountResetsAtTick) {
                 int i = this.getCompletionState();
+
                 this.brushCount = Math.max(0, this.brushCount - 2);
                 int j = this.getCompletionState();
+
                 if (i != j) {
-                    this.level.setBlock(this.getBlockPos(), this.getBlockState().setValue(BlockStateProperties.DUSTED, Integer.valueOf(j)), 3);
+                    this.level.setBlock(this.getBlockPos(), (BlockState) this.getBlockState().setValue(BlockStateProperties.DUSTED, j), 3);
                 }
 
-                int k = 4;
+                boolean flag = true;
+
                 this.brushCountResetsAtTick = this.level.getGameTime() + 4L;
             }
 
@@ -167,12 +196,13 @@
             } else {
                 this.level.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), 2);
             }
+
         }
     }
 
     private boolean tryLoadLootTable(CompoundTag nbt) {
         if (nbt.contains("LootTable", 8)) {
-            this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(nbt.getString("LootTable")));
+            this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
             this.lootTableSeed = nbt.getLong("LootTableSeed");
             return true;
         } else {
@@ -195,16 +225,17 @@
 
     @Override
     public CompoundTag getUpdateTag(HolderLookup.Provider registryLookup) {
-        CompoundTag compoundTag = super.getUpdateTag(registryLookup);
+        CompoundTag nbttagcompound = super.getUpdateTag(registryLookup);
+
         if (this.hitDirection != null) {
-            compoundTag.putInt("hit_direction", this.hitDirection.ordinal());
+            nbttagcompound.putInt("hit_direction", this.hitDirection.ordinal());
         }
 
         if (!this.item.isEmpty()) {
-            compoundTag.put("item", this.item.save(registryLookup));
+            nbttagcompound.put("item", this.item.save(registryLookup));
         }
 
-        return compoundTag;
+        return nbttagcompound;
     }
 
     @Override
@@ -216,7 +247,7 @@
     protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registryLookup) {
         super.loadAdditional(nbt, registryLookup);
         if (!this.tryLoadLootTable(nbt) && nbt.contains("item")) {
-            this.item = ItemStack.parse(registryLookup, nbt.getCompound("item")).orElse(ItemStack.EMPTY);
+            this.item = (ItemStack) ItemStack.parse(registryLookup, nbt.getCompound("item")).orElse(ItemStack.EMPTY);
         } else {
             this.item = ItemStack.EMPTY;
         }
@@ -224,6 +255,7 @@
         if (nbt.contains("hit_direction")) {
             this.hitDirection = Direction.values()[nbt.getInt("hit_direction")];
         }
+
     }
 
     @Override
@@ -232,6 +264,7 @@
         if (!this.trySaveLootTable(nbt) && !this.item.isEmpty()) {
             nbt.put("item", this.item.save(registryLookup));
         }
+
     }
 
     public void setLootTable(ResourceKey<LootTable> lootTable, long seed) {
@@ -240,13 +273,7 @@
     }
 
     private int getCompletionState() {
-        if (this.brushCount == 0) {
-            return 0;
-        } else if (this.brushCount < 3) {
-            return 1;
-        } else {
-            return this.brushCount < 6 ? 2 : 3;
-        }
+        return this.brushCount == 0 ? 0 : (this.brushCount < 3 ? 1 : (this.brushCount < 6 ? 2 : 3));
     }
 
     @Nullable
