PaperMC/patches/server/0978-Properly-handle-experience-dropping-on-block-break.patch
Owen 89d51d5f29
Allow enabling sand duping (#10191)
Because this exploit has been widely known for years and has not been fixed by Mojang, we decided that it was worth allowing people to toggle it on/off due to how easy it is to make it configurable.

It should be noted that this decision does not promise all future exploits will be configurable.
2024-03-03 17:05:34 -05:00

94 lines
7 KiB
Diff

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 6d98b910b1079f1b4a95c430e5500d55fbc68ec2..c0ae70e3490b56aaa464460e3c41175b27136f6b 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -625,7 +625,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); // Paper - Properly handle xp dropping
+ iblockdata.getBlock().popExperience((ServerLevel) this, pos, xp, breakingEntity); // Paper - Properly handle xp dropping; 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 c4bf01177b2dfcc88f6992dc85de216d448a79f8..6896d46fce2e466ebee23ac2dc00312ec1beefdb 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -321,23 +321,31 @@ public class Block extends BlockBehaviour implements ItemLike {
for (ItemStack drop : Block.getDrops(state, serverLevel, pos, blockEntity)) {
items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
}
+ Block block = state.getBlock(); // Paper - Properly handle xp dropping
io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, pos), org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, source), items);
+ event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
event.callEvent();
for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
popResource(serverLevel, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
}
- state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, true);
+ state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
+ block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
}
return true;
}
// Paper end - Add BlockBreakBlockEvent
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
+ // Paper start - Properly handle xp dropping
+ 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 - Properly handle xp dropping
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 - Properly handle xp dropping
}
}
@@ -421,7 +429,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 - fix drops not preventing stats/food exhaustion
- Block.dropResources(state, world, pos, blockEntity, player, tool);
+ Block.dropResources(state, world, pos, blockEntity, player, tool, dropExp); // Paper - Properly handle xp dropping
} // Paper - fix drops not preventing stats/food exhaustion
}
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 e57e3a26b0fb856e1ab693df5783fe8b9bee9719..64300077fce6eb28b6bddd42b3467eaa4c80c9f5 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
@@ -1183,6 +1183,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 - Properly handle xp dropping
}
public List<ItemStack> 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..4b42ef2a876ea210d948238e63fd7a2b7035bb5b 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 - Properly handle xp dropping
// Paper start - improve Block#breanNaturally
if (triggerEffect) {
if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {