diff --git a/patches/api/0168-BlockDestroyEvent.patch b/patches/api/0168-BlockDestroyEvent.patch
index c414a4253..5046b085e 100644
--- a/patches/api/0168-BlockDestroyEvent.patch
+++ b/patches/api/0168-BlockDestroyEvent.patch
@@ -12,10 +12,10 @@ This can replace many uses of BlockPhysicsEvent
diff --git a/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java
new file mode 100644
-index 0000000000000000000000000000000000000000..051b2ef76a914228338fa28553ad739bd2a0278c
+index 0000000000000000000000000000000000000000..5465f0dc890ad8825b910c2a77fd9c0868115ebe
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java
-@@ -0,0 +1,99 @@
+@@ -0,0 +1,121 @@
+package com.destroystokyo.paper.event.block;
+
+import org.bukkit.block.Block;
@@ -23,6 +23,7 @@ index 0000000000000000000000000000000000000000..051b2ef76a914228338fa28553ad739b
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.block.BlockEvent;
++import org.bukkit.event.block.BlockExpEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
@@ -36,23 +37,44 @@ index 0000000000000000000000000000000000000000..051b2ef76a914228338fa28553ad739b
+ * Events such as leaves decaying, pistons retracting (where the block is moving), does NOT fire this event.
+ *
+ */
-+public class BlockDestroyEvent extends BlockEvent implements Cancellable {
++public class BlockDestroyEvent extends BlockExpEvent implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ @NotNull private final BlockData newState;
+ private boolean willDrop;
+ private boolean playEffect = true;
++ private BlockData effectBlock;
+
+ private boolean cancelled = false;
+
+ public BlockDestroyEvent(@NotNull Block block, @NotNull BlockData newState, boolean willDrop) {
-+ super(block);
++ super(block, 0);
+ this.newState = newState;
+ this.willDrop = willDrop;
+ }
+
+ /**
++ * Get the effect that will be played when the block is broken.
++ * @return block break effect
++ */
++ @NotNull
++ public BlockData getEffectBlock() {
++ return this.effectBlock;
++ }
++
++ /**
++ * Sets the effect that will be played when the block is broken.
++ * Note: {@link BlockDestroyEvent#playEffect()} must be true in order for this effect to be
++ * played.
++ *
++ * @param effectBlock block effect
++ */
++ public void setEffectBlock(@NotNull BlockData effectBlock) {
++ this.effectBlock = effectBlock;
++ }
++
++ /**
+ * @return The new state of this block (Air, or a Fluid type)
+ */
+ @NotNull
diff --git a/patches/api/0310-Add-BlockBreakBlockEvent.patch b/patches/api/0310-Add-BlockBreakBlockEvent.patch
index dfd13b135..3ef95aee5 100644
--- a/patches/api/0310-Add-BlockBreakBlockEvent.patch
+++ b/patches/api/0310-Add-BlockBreakBlockEvent.patch
@@ -6,15 +6,16 @@ Subject: [PATCH] Add BlockBreakBlockEvent
diff --git a/src/main/java/io/papermc/paper/event/block/BlockBreakBlockEvent.java b/src/main/java/io/papermc/paper/event/block/BlockBreakBlockEvent.java
new file mode 100644
-index 0000000000000000000000000000000000000000..ac7a60403a9e51fc194f2cc92b0bd60d8879a661
+index 0000000000000000000000000000000000000000..51129c5c90dafdba08b7f533a71448ace56381d5
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/block/BlockBreakBlockEvent.java
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,60 @@
+package io.papermc.paper.event.block;
+
+import org.bukkit.block.Block;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.block.BlockEvent;
++import org.bukkit.event.block.BlockExpEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
@@ -25,7 +26,7 @@ index 0000000000000000000000000000000000000000..ac7a60403a9e51fc194f2cc92b0bd60d
+ *
+ * Currently called for piston's and liquid flows.
+ */
-+public class BlockBreakBlockEvent extends BlockEvent {
++public class BlockBreakBlockEvent extends BlockExpEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
@@ -33,7 +34,7 @@ index 0000000000000000000000000000000000000000..ac7a60403a9e51fc194f2cc92b0bd60d
+ private final Block source;
+
+ public BlockBreakBlockEvent(@NotNull Block block, @NotNull Block source, @NotNull List drops) {
-+ super(block);
++ super(block, 0);
+ this.source = source;
+ this.drops = drops;
+ }
diff --git a/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
index e0ceff545..a32b063cb 100644
--- a/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
+++ b/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
@@ -292,21 +292,21 @@ index 8d09c134058e55a23df4e23d965a7a783aed701e..45242f0ed5a0f98953df5f27fb76874d
world.levelEvent(1042, blockposition, 0);
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
-index 756a8ae14ffc46d6ebe0a858a03fb2e89b8e118a..bdf5443d5974d316b9b216291fadae4346a3123f 100644
+index 756a8ae14ffc46d6ebe0a858a03fb2e89b8e118a..89a62fbeeb78c864938a1cea84178478c6dc1b34 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -369,8 +369,13 @@ public class Block extends BlockBehaviour implements ItemLike {
}
public void popExperience(ServerLevel world, BlockPos pos, int size) {
-+ // Paper start - add player parameter
++ // Paper start - add entity parameter
+ popExperience(world, pos, size, null);
+ }
-+ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.server.level.ServerPlayer player) {
-+ // Paper end - add player parameter
++ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.world.entity.Entity entity) {
++ // Paper end - add entity parameter
if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
- ExperienceOrb.award(world, Vec3.atCenterOf(pos), size);
-+ ExperienceOrb.award(world, Vec3.atCenterOf(pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player); // Paper
++ ExperienceOrb.award(world, Vec3.atCenterOf(pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, entity); // Paper
}
}
diff --git a/patches/server/0288-BlockDestroyEvent.patch b/patches/server/0288-BlockDestroyEvent.patch
index 6b5aa51c8..65f26283b 100644
--- a/patches/server/0288-BlockDestroyEvent.patch
+++ b/patches/server/0288-BlockDestroyEvent.patch
@@ -11,7 +11,7 @@ floating in the air.
This can replace many uses of BlockPhysicsEvent
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 178509c545f2872174af501bdcec3314f703739c..d315a31f6b489ee88f81eb3d1b358c92e1e1619c 100644
+index b4f7e73fa673006ad0f8ea5a8de5a825aa75e41c..3ee67624e163a8c42cc8dab70aa05021baa2574b 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -31,6 +31,7 @@ import net.minecraft.nbt.CompoundTag;
@@ -22,7 +22,7 @@ index 178509c545f2872174af501bdcec3314f703739c..d315a31f6b489ee88f81eb3d1b358c92
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel;
-@@ -669,8 +670,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -669,9 +670,26 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return false;
} else {
FluidState fluid = this.getFluidState(pos);
@@ -30,18 +30,24 @@ index 178509c545f2872174af501bdcec3314f703739c..d315a31f6b489ee88f81eb3d1b358c92
+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent,
+ // it doesn't imply destruction of a block that plays a sound effect / drops an item.
+ boolean playEffect = true;
++ BlockState effectType = iblockdata;
++ int xp = iblockdata.getBlock().getExpDrop(iblockdata, (ServerLevel) this, pos, ItemStack.EMPTY, true);
+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop);
+ if (!event.callEvent()) {
+ return false;
+ }
++ effectType = ((CraftBlockData) event.getEffectBlock()).getState();
+ playEffect = event.playEffect();
+ drop = event.willDrop();
++ xp = event.getExpToDrop();
+ }
+ // Paper end
- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) {
-+ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper
- this.levelEvent(2001, pos, Block.getId(iblockdata));
+- this.levelEvent(2001, pos, Block.getId(iblockdata));
++ if (playEffect && !(effectType.getBlock() instanceof BaseFireBlock)) { // Paper
++ this.levelEvent(2001, pos, Block.getId(effectType)); // Paper
}
+ if (drop) {
diff --git a/patches/server/0302-Optimize-Captured-TileEntity-Lookup.patch b/patches/server/0302-Optimize-Captured-TileEntity-Lookup.patch
index d79b7937e..8f55396c3 100644
--- a/patches/server/0302-Optimize-Captured-TileEntity-Lookup.patch
+++ b/patches/server/0302-Optimize-Captured-TileEntity-Lookup.patch
@@ -10,10 +10,10 @@ Optimize to check if the captured list even has values in it, and also to
just do a get call since the value can never be null.
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 041984d629b7ddd2d2a856483fd69a2ab49c804e..8e5726194870f614b1522703f42fb11861bd7b9d 100644
+index be016a6fb0fcf1dfbce3fe6aca1085fbe883abdb..fdcc6666aa9100ddcf0d23a19bcd1dda29510d3e 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -994,9 +994,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -998,9 +998,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@Nullable
public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) {
diff --git a/patches/server/0365-Improved-Watchdog-Support.patch b/patches/server/0365-Improved-Watchdog-Support.patch
index f8b403470..7f3215ce5 100644
--- a/patches/server/0365-Improved-Watchdog-Support.patch
+++ b/patches/server/0365-Improved-Watchdog-Support.patch
@@ -271,7 +271,7 @@ index 109c7ff78d4c1f5496d294f52ecfd9df2070db1e..fe47a38137f7b7fa94c507e790eec4fb
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
-index 9036d9941b1597e14d3b25a5143d914248338800..f644c8b89e96d35fb9f2ac7941dcfcf9e8b66451 100644
+index c8a977f6dce36a254f729e97759c14e234ef6674..6d6cac755c45247e1d07e52550f6f4644536f220 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -532,7 +532,7 @@ public abstract class PlayerList {
@@ -296,10 +296,10 @@ index f5829ae484d93b547a5437b85a9621346384a11b..83701fbfaa56a232593ee8f11a3afb89
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 934a0de16e61de967d15b001bda45a97501dc658..4a097c3cf168005e2bae3ae484bc7ebd7a19a2d2 100644
+index 571019880cd9f22f347ac8fca663728b6706912d..7d213ebc6a3d9dc15468a6cfb472306121c3ca15 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -909,6 +909,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -913,6 +913,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
try {
tickConsumer.accept(entity);
} catch (Throwable throwable) {
diff --git a/patches/server/0678-Execute-chunk-tasks-mid-tick.patch b/patches/server/0678-Execute-chunk-tasks-mid-tick.patch
index d42293cee..d11ebf316 100644
--- a/patches/server/0678-Execute-chunk-tasks-mid-tick.patch
+++ b/patches/server/0678-Execute-chunk-tasks-mid-tick.patch
@@ -151,10 +151,10 @@ index a885b90a44066103133af953d56bb3dbb9b899be..2c759854ed9f78c48c4e9ed2dc72e5a5
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index e939b572c4e9bb316b342cdadf116942f04f53b2..17b7f100979042ef33e18ab930a0935e4cfaa674 100644
+index 73d3eff15c3faea7716beb5b53d66af434005d0f..cddac4571578ac8d647f3f4b20fb6f7b773aabe3 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -923,6 +923,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -927,6 +927,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Spigot end
} else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) {
tickingblockentity.tick();
@@ -166,7 +166,7 @@ index e939b572c4e9bb316b342cdadf116942f04f53b2..17b7f100979042ef33e18ab930a0935e
}
}
this.blockEntityTickers.removeAll(toRemove);
-@@ -937,6 +942,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -941,6 +946,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public void guardEntityTick(Consumer tickConsumer, T entity) {
try {
tickConsumer.accept(entity);
diff --git a/patches/server/0681-Optimise-random-block-ticking.patch b/patches/server/0681-Optimise-random-block-ticking.patch
index 695231a1d..112c88e4d 100644
--- a/patches/server/0681-Optimise-random-block-ticking.patch
+++ b/patches/server/0681-Optimise-random-block-ticking.patch
@@ -327,7 +327,7 @@ diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/
index 17b7f100979042ef33e18ab930a0935e4cfaa674..c438c75b8edfbb8d728b01a96882e6cd802a3bea 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -1394,10 +1394,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1398,10 +1398,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public abstract RecipeManager getRecipeManager();
public BlockPos getBlockRandomPos(int x, int y, int z, int l) {
diff --git a/patches/server/0717-Collision-optimisations.patch b/patches/server/0717-Collision-optimisations.patch
index 5b51e21cb..380f7a085 100644
--- a/patches/server/0717-Collision-optimisations.patch
+++ b/patches/server/0717-Collision-optimisations.patch
@@ -2179,7 +2179,7 @@ index d0a8092bf57a29ab7c00ec0ddf52a9fdb2a33267..392406722b0a040c1d41fdc1154d75d3
private Direction(int id, int idOpposite, int idHorizontal, String name, Direction.AxisDirection direction, Direction.Axis axis, Vec3i vector) {
this.data3d = id;
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 45f2a81cd59434956cc33e489af6032e6ef9947d..29da0b80aa0a4e6ebf1f0e30c26a6b85f034e8e4 100644
+index 60164d8ff63bf536ddf46605a9dc7931ebc5b82a..7c8f5ae6bd83bd08403738dcd364b0af06fb1a9b 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -469,7 +469,7 @@ public class ServerPlayer extends Player {
@@ -2201,7 +2201,7 @@ index 45f2a81cd59434956cc33e489af6032e6ef9947d..29da0b80aa0a4e6ebf1f0e30c26a6b85
}
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
-index 53dbfb828f4d6f47b87e7ff6829a8dbc3de2f0fd..30ad9f878d0b76c6bef594448c3122d614a7aa8c 100644
+index 159932e2807c8d51fbf141c2145a138a39ea8abe..41a5d509a398972db910d32babb70e9bd5fa41da 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -911,7 +911,7 @@ public abstract class PlayerList {
@@ -2600,7 +2600,7 @@ index a25497eec004add7408a63b1a0f09e3fa443b324..9f892de55ab03367daed4c30cc44c9dd
// Paper start
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 0bf3bfd0a44fe7219e6ed451eb85c25e87a31aac..3dfc42dfed0429ea46238ede127b86a0c7756659 100644
+index 126d37e14ff785c17e45d4601131156593f5ace5..096cd97827f4912fc5b538e01d29257195270055 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -300,6 +300,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -2985,7 +2985,7 @@ index 0bf3bfd0a44fe7219e6ed451eb85c25e87a31aac..3dfc42dfed0429ea46238ede127b86a0
@Override
public boolean isClientSide() {
return this.isClientSide;
-@@ -957,7 +1325,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -961,7 +1329,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@Override
public boolean noCollision(@Nullable Entity entity, AABB box) {
if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return false;
@@ -3005,7 +3005,7 @@ index 0bf3bfd0a44fe7219e6ed451eb85c25e87a31aac..3dfc42dfed0429ea46238ede127b86a0
// Paper end
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
-index f0a85f1b48a911ffd8740df5ebe869e8f0371a58..7ac98b4e8b6dcc23777732d377ee73ae5671ebef 100644
+index 49aa9020290e4466eb386400b4a6e5284cfe355b..5343a0c20cf87067ba307f001a28b0b18fae2c34 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -284,7 +284,7 @@ public class Block extends BlockBehaviour implements ItemLike {
diff --git a/patches/server/0806-Add-Alternate-Current-redstone-implementation.patch b/patches/server/0806-Add-Alternate-Current-redstone-implementation.patch
index 51458c3c4..cb2ce69dc 100644
--- a/patches/server/0806-Add-Alternate-Current-redstone-implementation.patch
+++ b/patches/server/0806-Add-Alternate-Current-redstone-implementation.patch
@@ -2034,10 +2034,10 @@ index 9e0fb3a13cd4ae0142e3e63995b7eac61e48eea6..8587f35706daf5a317035d0f7acee0b3
EntityCallbacks() {}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index b4c4e90994f8872c2f648389c7de0dd31a874085..cdd8cedc524ddbd0332b7198c78f65dff59423bc 100644
+index 096cd97827f4912fc5b538e01d29257195270055..6ad9e4da7fd9d8b4e482928295b51e13170ed6b9 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -1881,4 +1881,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1885,4 +1885,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return range <= 0 ? 64.0 * 64.0 : range * range; // 64 is taken from default in ServerLevel#levelEvent
}
// Paper end - respect global sound events gamerule
diff --git a/patches/server/0967-Only-capture-actual-tree-growth.patch b/patches/server/0967-Only-capture-actual-tree-growth.patch
index bd43e01cd..df56cb240 100644
--- a/patches/server/0967-Only-capture-actual-tree-growth.patch
+++ b/patches/server/0967-Only-capture-actual-tree-growth.patch
@@ -29,10 +29,10 @@ index db523ded8132f2010391c9f909319d0ae042a741..852727221d5cb8bcc14c57664622c13d
}
entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 013a6c551958af4c41814f66948998aff4842d52..1d8ad95f4fbf77b1c94be9bbe5aeb18601156765 100644
+index 9bcbc7ca5da57aa80dacaa89c1af51fab3548152..6e46124d67b6c25155a9942b04c09f3dc946a249 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -1894,4 +1894,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1898,4 +1898,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return null;
}
// Paper end - optimize redstone (Alternate Current)
diff --git a/patches/server/0980-Properly-handle-BlockBreakEvent-isDropItems.patch b/patches/server/0980-Properly-handle-BlockBreakEvent-isDropItems.patch
index 8808e90bd..f180ec4e5 100644
--- a/patches/server/0980-Properly-handle-BlockBreakEvent-isDropItems.patch
+++ b/patches/server/0980-Properly-handle-BlockBreakEvent-isDropItems.patch
@@ -9,7 +9,7 @@ food consumption, turtle egg count decreases, ice to water
conversions and beehive releases
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
-index 82f26186156a487f29ad3abff3f68852e5b8a1f9..511221a686c1d2cad3b4abf79ee32b26058dad27 100644
+index 82f26186156a487f29ad3abff3f68852e5b8a1f9..e2764751aaa862e3e0c21cf9a8ab66ed921c65e5 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -433,8 +433,8 @@ public class ServerPlayerGameMode {
@@ -19,12 +19,12 @@ index 82f26186156a487f29ad3abff3f68852e5b8a1f9..511221a686c1d2cad3b4abf79ee32b26
- if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items
- block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1);
+ if (flag && flag1 && event.isDropItems()/* && event.isDropItems() */) { // CraftBukkit - Check if block should drop items // Paper - fix drops not preventing stats/food exhaustion
-+ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems()); // Paper
++ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems(), false); // Paper
}
// return true; // CraftBukkit
diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
-index 6e7a9f68aa3a5084c8eea9fd8721272260734289..7d1f3c367efcf8def56b961993136e02e05ba59c 100644
+index 6e7a9f68aa3a5084c8eea9fd8721272260734289..2594c8e233114b21e5b00acb5ad7012b004a0ef2 100644
--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
@@ -84,8 +84,8 @@ public class BeehiveBlock extends BaseEntityBlock {
@@ -33,13 +33,13 @@ index 6e7a9f68aa3a5084c8eea9fd8721272260734289..7d1f3c367efcf8def56b961993136e02
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
-+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) { // Paper
-+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
++ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper
if (!world.isClientSide && blockEntity instanceof BeehiveBlockEntity) {
BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) blockEntity;
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
-index 7ac98b4e8b6dcc23777732d377ee73ae5671ebef..4d50dd92a7f3187ee1d8edb926e7c273c8156549 100644
+index 5343a0c20cf87067ba307f001a28b0b18fae2c34..0011bbb22fcfba267818c55b03042db5e67be562 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -423,10 +423,18 @@ public class Block extends BlockBehaviour implements ItemLike {
@@ -49,9 +49,9 @@ index 7ac98b4e8b6dcc23777732d377ee73ae5671ebef..4d50dd92a7f3187ee1d8edb926e7c273
+ @io.papermc.paper.annotation.DoNotUse // Paper - method below allows better control of item drops
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
+ // Paper start
-+ this.playerDestroy(world, player, pos, state, blockEntity, tool, true);
++ this.playerDestroy(world, player, pos, state, blockEntity, tool, true, true);
+ }
-+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) {
++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) {
+ // Paper end
player.awardStat(Stats.BLOCK_MINED.get(this));
player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
@@ -62,7 +62,7 @@ index 7ac98b4e8b6dcc23777732d377ee73ae5671ebef..4d50dd92a7f3187ee1d8edb926e7c273
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
-index 0f0750f8c790d0db72a0e6b277449a1461674890..81d2140351775ad55546af52eb635ccdc8509d89 100644
+index 0f0750f8c790d0db72a0e6b277449a1461674890..a6a257027d60bfda8cb975eca7f255fb1bd1e8d5 100644
--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
@@ -96,8 +96,8 @@ public class DoublePlantBlock extends BushBlock {
@@ -71,13 +71,13 @@ index 0f0750f8c790d0db72a0e6b277449a1461674890..81d2140351775ad55546af52eb635ccd
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool);
-+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) { // Paper
-+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops); // Paper
++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
++ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper
}
protected static void preventDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) {
diff --git a/src/main/java/net/minecraft/world/level/block/IceBlock.java b/src/main/java/net/minecraft/world/level/block/IceBlock.java
-index f05998e0af1e844f19bf86b74f652a9901088c37..4ab6997dad5b112f5105f786a6cee78c6c5667e8 100644
+index f05998e0af1e844f19bf86b74f652a9901088c37..9ebe74e235d425fde985a6180857dc4039ecfedf 100644
--- a/src/main/java/net/minecraft/world/level/block/IceBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/IceBlock.java
@@ -33,8 +33,8 @@ public class IceBlock extends HalfTransparentBlock {
@@ -86,13 +86,13 @@ index f05998e0af1e844f19bf86b74f652a9901088c37..4ab6997dad5b112f5105f786a6cee78c
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
-+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) { // Paper
-+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
++ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper
// Paper start
this.afterDestroy(world, pos, tool);
}
diff --git a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
-index c79f3a8885a5ffc9ebac51992e63df14929d9f24..b0199e071cba4c7ad51799132d00b22b616953fc 100644
+index c79f3a8885a5ffc9ebac51992e63df14929d9f24..5c0127ecbbafd406f450f8707c4563bfea7a0214 100644
--- a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -173,8 +173,8 @@ public class TurtleEggBlock extends Block {
@@ -101,8 +101,8 @@ index c79f3a8885a5ffc9ebac51992e63df14929d9f24..b0199e071cba4c7ad51799132d00b22b
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
-+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) { // Paper
-+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
++ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper
this.decreaseEggs(world, pos, state);
}
diff --git a/patches/server/1004-Fix-silent-equipment-change-for-mobs.patch b/patches/server/1004-Fix-silent-equipment-change-for-mobs.patch
index 2812d9c2d..2b994e5be 100644
--- a/patches/server/1004-Fix-silent-equipment-change-for-mobs.patch
+++ b/patches/server/1004-Fix-silent-equipment-change-for-mobs.patch
@@ -47,10 +47,10 @@ index 8e9469fec42f7b6a132cf173f6f5a95777a29b3b..b319021b22c5dceba6199ed27814b2dc
this.reassessWeaponGoal();
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 1d8ad95f4fbf77b1c94be9bbe5aeb18601156765..8848eeda7a89d445e370626182f9bb4710e5edd4 100644
+index 6e46124d67b6c25155a9942b04c09f3dc946a249..cdd03a1602cef13d2e62e6a6655ec2929e0d590f 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -1896,7 +1896,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1900,7 +1900,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Paper end - optimize redstone (Alternate Current)
// Paper start - notify observers even if grow failed
public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final CraftBlockState craftBlockState) {
diff --git a/patches/server/1061-Properly-handle-experience-dropping-on-block-break.patch b/patches/server/1061-Properly-handle-experience-dropping-on-block-break.patch
new file mode 100644
index 000000000..24147f07c
--- /dev/null
+++ b/patches/server/1061-Properly-handle-experience-dropping-on-block-break.patch
@@ -0,0 +1,94 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
+Date: Sat, 30 Dec 2023 15:00:06 -0500
+Subject: [PATCH] Properly handle experience dropping on block break
+
+This causes spawnAfterBreak to spawn xp by default, removing the need to manually add xp wherever this method is used.
+For classes that use custom xp amounts, they can drop the resources with disabling
+
+diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
+index 380b6bc69429ec8bd92f0adf90b02028fec23d52..c7021d31fe392536efdfbf08b7e7df834d3d8a98 100644
+--- a/src/main/java/net/minecraft/world/level/Level.java
++++ b/src/main/java/net/minecraft/world/level/Level.java
+@@ -1103,7 +1103,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ if (drop) {
+ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
+
+- Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY);
++ Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY, false); // Don't drop xp
++ iblockdata.getBlock().popExperience((ServerLevel) this, pos, xp, breakingEntity); // Paper - handle drop experience logic, custom amount
+ }
+
+ boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth);
+diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
+index 0011bbb22fcfba267818c55b03042db5e67be562..c390fe88a6756e6759050d88e3c6df2b0e0efaed 100644
+--- a/src/main/java/net/minecraft/world/level/block/Block.java
++++ b/src/main/java/net/minecraft/world/level/block/Block.java
+@@ -333,23 +333,31 @@ public class Block extends BlockBehaviour implements ItemLike {
+ for (net.minecraft.world.item.ItemStack drop : net.minecraft.world.level.block.Block.getDrops(state, world.getMinecraftWorld(), pos, blockEntity)) {
+ items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
+ }
++ Block block = state.getBlock();
+ io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.block.CraftBlock.at(world, source), items);
++ event.setExpToDrop(block.getExpDrop(state, (ServerLevel) world, pos, net.minecraft.world.item.ItemStack.EMPTY, true));
+ event.callEvent();
+ for (var drop : event.getDrops()) {
+ popResource(world.getMinecraftWorld(), pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
+ }
+- state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, true);
++ state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, false);
++ block.popExperience((ServerLevel) world, pos, event.getExpToDrop());
+ }
+ return true;
+ }
+ // Paper end
+
+ public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
++ // Paper start
++ dropResources(state, world, pos, blockEntity, entity, tool, true);
++ }
++ public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool, boolean dropExperience) {
++ // Paper end
+ if (world instanceof ServerLevel) {
+ Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
+ Block.popResource(world, pos, itemstack1);
+ });
+- state.spawnAfterBreak((ServerLevel) world, pos, tool, true);
++ state.spawnAfterBreak((ServerLevel) world, pos, tool, dropExperience); // Paper
+ }
+
+ }
+@@ -433,7 +441,7 @@ public class Block extends BlockBehaviour implements ItemLike {
+ player.awardStat(Stats.BLOCK_MINED.get(this));
+ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
+ if (includeDrops) { // Paper
+- Block.dropResources(state, world, pos, blockEntity, player, tool);
++ Block.dropResources(state, world, pos, blockEntity, player, tool, dropExp); // Paper
+ } // Paper
+ }
+
+diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+index 3ab8b99837b1d1faea722c598b0228b2780be8b1..401f1b418a4f57059e991cc958ebadb31239a581 100644
+--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+@@ -1286,6 +1286,7 @@ public abstract class BlockBehaviour implements FeatureElement {
+
+ public void spawnAfterBreak(ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) {
+ this.getBlock().spawnAfterBreak(this.asState(), world, pos, tool, dropExperience);
++ if (dropExperience) {getBlock().popExperience(world, pos, this.getBlock().getExpDrop(asState(), world, pos, tool, true));} // Paper - spawn experience
+ }
+
+ public List getDrops(LootParams.Builder builder) {
+diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+index e5506a7d074a9f89d41f4d5d7549a458779bef20..520b53bc604e6755251f0b14e91dce56bc5501ce 100644
+--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+@@ -503,7 +503,7 @@ public class CraftBlock implements Block {
+
+ // Modelled off EntityHuman#hasBlock
+ if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) {
+- net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem);
++ net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem, false); // Paper
+ // Paper start - improve Block#breanNaturally
+ if (triggerEffect) {
+ if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {