mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-02 04:56:50 +01:00
89d51d5f29
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.
161 lines
11 KiB
Diff
161 lines
11 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
|
Date: Sat, 4 Mar 2023 10:52:52 -0800
|
|
Subject: [PATCH] Properly handle BlockBreakEvent#isDropItems
|
|
|
|
Setting whether a block break dropped items controlled
|
|
far more than just whether blocks dropped, like stat increases
|
|
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 3621770701c6fb1da75c69a41297684493380e37..4747b05619f37009a5a236678aceec6cfc1c0b79 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
@@ -431,8 +431,8 @@ public class ServerPlayerGameMode {
|
|
isCorrectTool = flag1; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
|
|
|
itemstack.mineBlock(this.level, iblockdata1, pos, this.player);
|
|
- 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() */) { // 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(), false); // Paper - fix drops not preventing stats/food exhaustion
|
|
}
|
|
|
|
// 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 799e44ae5a7c3d6994653d43d455c39f3e30b012..25e8d6066fb94d0b9a244ab1fec5139b9266d86d 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 {
|
|
}
|
|
|
|
@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, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
|
|
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
|
|
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 57d92c1785586dfab2b3934733d8ba253e042e2e..c4bf01177b2dfcc88f6992dc85de216d448a79f8 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
|
@@ -411,10 +411,18 @@ public class Block extends BlockBehaviour implements ItemLike {
|
|
return this.defaultBlockState();
|
|
}
|
|
|
|
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - fix drops not preventing stats/food exhaustion
|
|
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
|
|
+ // Paper start - fix drops not preventing stats/food exhaustion
|
|
+ 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, boolean dropExp) {
|
|
+ // Paper end - fix drops not preventing stats/food exhaustion
|
|
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);
|
|
+ } // Paper - fix drops not preventing stats/food exhaustion
|
|
}
|
|
|
|
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..03b5ab8251497c0c94467f90e6663a0dc766babb 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 {
|
|
}
|
|
|
|
@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, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
|
|
+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
|
|
}
|
|
|
|
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 52c6c26a300cfd19c478afba411a17c8d5ea0c3c..9c8c1df5187daefb1c8098b4d4a0976c71a7bbfd 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 {
|
|
}
|
|
|
|
@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, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
|
|
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
|
|
// Paper start - Improve Block#breakNaturally API
|
|
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..b4646e26965e0f1f26c5019e7c6a13fdf22bdb47 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 {
|
|
}
|
|
|
|
@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, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
|
|
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
|
|
this.decreaseEggs(world, pos, state);
|
|
}
|
|
|
|
diff --git a/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java b/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..7c435f7079b429873f33d7bade82eca0c6b45842
|
|
--- /dev/null
|
|
+++ b/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java
|
|
@@ -0,0 +1,47 @@
|
|
+package io.papermc.paper.world.block;
|
|
+
|
|
+import io.github.classgraph.ClassGraph;
|
|
+import io.github.classgraph.ClassInfo;
|
|
+import io.github.classgraph.MethodInfo;
|
|
+import io.github.classgraph.MethodInfoList;
|
|
+import io.github.classgraph.MethodParameterInfo;
|
|
+import io.github.classgraph.ScanResult;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.stream.Stream;
|
|
+import org.bukkit.support.AbstractTestingBase;
|
|
+import org.junit.jupiter.params.ParameterizedTest;
|
|
+import org.junit.jupiter.params.provider.MethodSource;
|
|
+
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
+
|
|
+public class BlockPlayerDestroyOverrideTest extends AbstractTestingBase {
|
|
+
|
|
+ public static Stream<ClassInfo> parameters() {
|
|
+ final List<ClassInfo> classInfo = new ArrayList<>();
|
|
+ try (ScanResult scanResult = new ClassGraph()
|
|
+ .enableClassInfo()
|
|
+ .enableMethodInfo()
|
|
+ .whitelistPackages("net.minecraft")
|
|
+ .scan()
|
|
+ ) {
|
|
+ for (final ClassInfo subclass : scanResult.getSubclasses("net.minecraft.world.level.block.Block")) {
|
|
+ final MethodInfoList playerDestroy = subclass.getDeclaredMethodInfo("playerDestroy");
|
|
+ if (!playerDestroy.isEmpty()) {
|
|
+ classInfo.add(subclass);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return classInfo.stream();
|
|
+ }
|
|
+
|
|
+ @ParameterizedTest
|
|
+ @MethodSource("parameters")
|
|
+ public void checkPlayerDestroyOverrides(ClassInfo overridesPlayerDestroy) {
|
|
+ final MethodInfoList playerDestroy = overridesPlayerDestroy.getDeclaredMethodInfo("playerDestroy");
|
|
+ assertEquals(1, playerDestroy.size(), overridesPlayerDestroy.getName() + " has multiple playerDestroy methods");
|
|
+ final MethodInfo next = playerDestroy.iterator().next();
|
|
+ final MethodParameterInfo[] parameterInfo = next.getParameterInfo();
|
|
+ assertEquals("boolean", parameterInfo[parameterInfo.length - 1].getTypeDescriptor().toStringWithSimpleNames(), overridesPlayerDestroy.getName() + " needs to change its override of playerDestroy");
|
|
+ }
|
|
+}
|