From 96d7b7b6e469f4fe19ba89e9c69d8e2fe807d944 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Wed, 14 Dec 2022 19:37:16 -0800 Subject: [PATCH] Add more breakNaturally functionality (#7379) --- .../Add-effect-to-block-break-naturally.patch | 37 -------- patches/api/Block-Ticking-API.patch | 2 +- .../Improve-Block-breakNaturally-API.patch | 68 +++++++++++++ .../Add-effect-to-block-break-naturally.patch | 37 -------- ...luid-logging-on-Block-breakNaturally.patch | 29 ------ .../Improve-Block-breakNaturally-API.patch | 95 +++++++++++++++++++ 6 files changed, 164 insertions(+), 104 deletions(-) delete mode 100644 patches/api/Add-effect-to-block-break-naturally.patch create mode 100644 patches/api/Improve-Block-breakNaturally-API.patch delete mode 100644 patches/server/Add-effect-to-block-break-naturally.patch delete mode 100644 patches/server/Fix-fluid-logging-on-Block-breakNaturally.patch create mode 100644 patches/server/Improve-Block-breakNaturally-API.patch diff --git a/patches/api/Add-effect-to-block-break-naturally.patch b/patches/api/Add-effect-to-block-break-naturally.patch deleted file mode 100644 index 5017055439..0000000000 --- a/patches/api/Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:16 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -0,0 +0,0 @@ public interface Block extends Metadatable { - */ - boolean breakNaturally(@Nullable ItemStack tool); - -+ // Paper start -+ /** -+ * Breaks the block and spawns item drops as if a player had broken it -+ * -+ * @param triggerEffect Play the block break particle effect and sound -+ * @return true if the block was destroyed -+ */ -+ boolean breakNaturally(boolean triggerEffect); -+ -+ /** -+ * Breaks the block and spawns item drops as if a player had broken it -+ * with a specific tool -+ * -+ * @param tool The tool or item in hand used for digging -+ * @param triggerEffect Play the block break particle effect and sound -+ * @return true if the block was destroyed -+ */ -+ boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect); -+ // Paper end -+ - /** - * Simulate bone meal application to this block (if possible). - * diff --git a/patches/api/Block-Ticking-API.patch b/patches/api/Block-Ticking-API.patch index dd89238668..16a3dfd263 100644 --- a/patches/api/Block-Ticking-API.patch +++ b/patches/api/Block-Ticking-API.patch @@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public interface Block extends Metadatable, net.kyori.adventure.translation.Tran * @return true if the block was destroyed */ - boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect); + boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect, boolean dropExperience); + + /** + * Causes the block to be ticked, this is different from {@link Block#randomTick()}, diff --git a/patches/api/Improve-Block-breakNaturally-API.patch b/patches/api/Improve-Block-breakNaturally-API.patch new file mode 100644 index 0000000000..0890fbef19 --- /dev/null +++ b/patches/api/Improve-Block-breakNaturally-API.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 2 Jan 2020 12:25:16 -0600 +Subject: [PATCH] Improve Block#breakNaturally API + +Adds bool param to trigger world particle effects + +Adds bool param to trigger exp drops for blocks + +Co-authored-by: William Blake Galbreath + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -0,0 +0,0 @@ public interface Block extends Metadatable { + */ + boolean breakNaturally(@Nullable ItemStack tool); + ++ // Paper start ++ /** ++ * Breaks the block and spawns item drops as if a player had broken it ++ * ++ * @param triggerEffect Play the block break particle effect and sound ++ * @return true if the block was destroyed ++ * @see #breakNaturally(boolean, boolean) to trigger exp drops ++ */ ++ default boolean breakNaturally(boolean triggerEffect) { ++ return this.breakNaturally(triggerEffect, false); ++ } ++ ++ /** ++ * Breaks the block and spawns item drops as if a player had broken it ++ * ++ * @param triggerEffect Play the block break particle effect and sound ++ * @param dropExperience drop exp if the block normally does so ++ * @return true if the block was destroyed ++ */ ++ boolean breakNaturally(boolean triggerEffect, boolean dropExperience); ++ ++ /** ++ * Breaks the block and spawns item drops as if a player had broken it ++ * with a specific tool ++ * ++ * @param tool The tool or item in hand used for digging ++ * @param triggerEffect Play the block break particle effect and sound ++ * @return true if the block was destroyed ++ * @see #breakNaturally(ItemStack, boolean, boolean) to trigger exp drops ++ */ ++ default boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect) { ++ return this.breakNaturally(tool, triggerEffect, false); ++ } ++ ++ /** ++ * Breaks the block and spawns item drops as if a player had broken it ++ * with a specific tool ++ * ++ * @param tool The tool or item in hand used for digging ++ * @param triggerEffect Play the block break particle effect and sound ++ * @param dropExperience drop exp if the block normally does so ++ * @return true if the block was destroyed ++ */ ++ boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect, boolean dropExperience); ++ // Paper end ++ + /** + * Simulate bone meal application to this block (if possible). + * diff --git a/patches/server/Add-effect-to-block-break-naturally.patch b/patches/server/Add-effect-to-block-break-naturally.patch deleted file mode 100644 index 1d04323a02..0000000000 --- a/patches/server/Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:07 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - - @Override - public boolean breakNaturally(ItemStack item) { -+ // Paper start -+ return breakNaturally(item, false); -+ } -+ -+ @Override -+ public boolean breakNaturally(boolean triggerEffect) { -+ return breakNaturally(null, triggerEffect); -+ } -+ -+ @Override -+ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { -+ // Paper end - // Order matters here, need to drop before setting to air so skulls can get their data - net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); - net.minecraft.world.level.block.Block block = iblockdata.getBlock(); -@@ -0,0 +0,0 @@ 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(), position, this.world.getBlockEntity(position), null, nmsItem); -+ if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper - result = true; - } - diff --git a/patches/server/Fix-fluid-logging-on-Block-breakNaturally.patch b/patches/server/Fix-fluid-logging-on-Block-breakNaturally.patch deleted file mode 100644 index 843cbe3efa..0000000000 --- a/patches/server/Fix-fluid-logging-on-Block-breakNaturally.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 21 Dec 2021 16:28:17 -0800 -Subject: [PATCH] Fix fluid-logging on Block#breakNaturally - -Leaves fluid if the block broken was fluid-logged which is what -happens if a player breaks a fluid-logged block - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); - net.minecraft.world.level.block.Block block = iblockdata.getBlock(); - net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item); -+ net.minecraft.world.level.material.FluidState fluidState = this.world.getFluidState(this.position); // Paper - boolean result = false; - - // Modelled off EntityHuman#hasBlock -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - } - - // SPIGOT-6778: Directly call setBlock instead of setTypeAndData, so that the tile entiy is not removed and custom remove logic is run. -- return this.world.setBlock(position, Blocks.AIR.defaultBlockState(), 3) && result; -+ return this.world.setBlock(position, fluidState.createLegacyBlock(), 3) && result; // Paper - leave liquid if waterlogged - } - - @Override diff --git a/patches/server/Improve-Block-breakNaturally-API.patch b/patches/server/Improve-Block-breakNaturally-API.patch new file mode 100644 index 0000000000..7bcbefb049 --- /dev/null +++ b/patches/server/Improve-Block-breakNaturally-API.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 2 Jan 2020 12:25:07 -0600 +Subject: [PATCH] Improve Block#breakNaturally API + +Adds bool parameter to play world effect on block break + +Adds bool parameter to drop xp from blocks + +Fixes fluid-logged blocks not leaving fluid behind if +broken + +Handles special cases for ice and turtle eggs + +== AT == +public net.minecraft.world.level.block.TurtleEggBlock decreaseEggs(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V + +Co-authored-by: William Blake Galbreath + +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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/IceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/IceBlock.java +@@ -0,0 +0,0 @@ public class IceBlock extends HalfTransparentBlock { + @Override + public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) { + super.playerDestroy(world, player, pos, state, blockEntity, stack); ++ // Paper start ++ this.afterDestroy(world, pos, stack); ++ } ++ public void afterDestroy(Level world, BlockPos pos, ItemStack stack) { ++ // Paper end + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { + if (world.dimensionType().ultraWarm()) { + world.removeBlock(pos, false); +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -0,0 +0,0 @@ public class CraftBlock implements Block { + + @Override + public boolean breakNaturally(ItemStack item) { ++ // Paper start ++ return this.breakNaturally(item, false); ++ } ++ ++ @Override ++ public boolean breakNaturally(boolean triggerEffect, boolean dropExperience) { ++ return this.breakNaturally(null, triggerEffect, dropExperience); ++ } ++ ++ @Override ++ public boolean breakNaturally(ItemStack item, boolean triggerEffect, boolean dropExperience) { ++ // Paper end + // Order matters here, need to drop before setting to air so skulls can get their data + net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); + net.minecraft.world.level.block.Block block = iblockdata.getBlock(); +@@ -0,0 +0,0 @@ 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(), position, this.world.getBlockEntity(position), null, nmsItem); ++ // Paper start - improve Block#breanNaturally ++ if (triggerEffect) { ++ if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) { ++ this.world.levelEvent(net.minecraft.world.level.block.LevelEvent.SOUND_EXTINGUISH_FIRE, this.position, 0); ++ } else { ++ this.world.levelEvent(net.minecraft.world.level.block.LevelEvent.PARTICLES_DESTROY_BLOCK, this.position, net.minecraft.world.level.block.Block.getId(iblockdata)); ++ } ++ } ++ if (dropExperience) block.popExperience(this.world.getMinecraftWorld(), this.position, block.getExpDrop(iblockdata, this.world.getMinecraftWorld(), this.position, nmsItem, true)); ++ // Paper end + result = true; + } + + // SPIGOT-6778: Directly call setBlock instead of setTypeAndData, so that the tile entiy is not removed and custom remove logic is run. +- return this.world.setBlock(position, Blocks.AIR.defaultBlockState(), 3) && result; ++ // Paper start - improve breakNaturally ++ boolean destroyed = this.world.removeBlock(this.position, false); ++ if (destroyed) { ++ block.destroy(this.world, this.position, iblockdata); ++ } ++ if (result) { ++ // special cases ++ if (block instanceof net.minecraft.world.level.block.IceBlock iceBlock) { ++ iceBlock.afterDestroy(this.world.getMinecraftWorld(), this.position, nmsItem); ++ } else if (block instanceof net.minecraft.world.level.block.TurtleEggBlock turtleEggBlock) { ++ turtleEggBlock.decreaseEggs(this.world.getMinecraftWorld(), this.position, iblockdata); ++ } ++ } ++ return destroyed && result; ++ // Paper end + } + + @Override