diff --git a/patches/server/1062-Call-bucket-events-for-cauldrons.patch b/patches/server/1062-Call-bucket-events-for-cauldrons.patch new file mode 100644 index 0000000000..dfb8d7f8e2 --- /dev/null +++ b/patches/server/1062-Call-bucket-events-for-cauldrons.patch @@ -0,0 +1,190 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 16 Jan 2022 10:13:33 -0800 +Subject: [PATCH] Call bucket events for cauldrons + + +diff --git a/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java b/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java +index f301c20e808b77cb3fcffd9a7c8102928306456e..b584cfe44fbb93d470ca56c091423833c4007d16 100644 +--- a/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java ++++ b/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java +@@ -60,7 +60,7 @@ public interface CauldronInteraction { + static CauldronInteraction.InteractionMap newInteractionMap(String name) { + Object2ObjectOpenHashMap object2objectopenhashmap = new Object2ObjectOpenHashMap(); + +- object2objectopenhashmap.defaultReturnValue((iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ object2objectopenhashmap.defaultReturnValue((iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + }); + CauldronInteraction.InteractionMap cauldroninteraction_a = new CauldronInteraction.InteractionMap(name, object2objectopenhashmap); +@@ -69,13 +69,13 @@ public interface CauldronInteraction { + return cauldroninteraction_a; + } + +- ItemInteractionResult interact(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack); ++ ItemInteractionResult interact(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection); // Paper - add hitDirection + + static void bootStrap() { + Map map = CauldronInteraction.EMPTY.map(); + + CauldronInteraction.addDefaultInteractions(map); +- map.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ map.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + PotionContents potioncontents = (PotionContents) itemstack.get(DataComponents.POTION_CONTENTS); + + if (potioncontents != null && potioncontents.is(Potions.WATER)) { +@@ -103,12 +103,12 @@ public interface CauldronInteraction { + Map map1 = CauldronInteraction.WATER.map(); + + CauldronInteraction.addDefaultInteractions(map1); +- map1.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ map1.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + return CauldronInteraction.fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.WATER_BUCKET), (iblockdata1) -> { + return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3; +- }, SoundEvents.BUCKET_FILL); ++ }, SoundEvents.BUCKET_FILL, hitDirection); // Paper - add hitDirection + }); +- map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + if (!world.isClientSide) { + // CraftBukkit start + if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) { +@@ -127,7 +127,7 @@ public interface CauldronInteraction { + + return ItemInteractionResult.sidedSuccess(world.isClientSide); + }); +- map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) == 3) { + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } else { +@@ -194,15 +194,15 @@ public interface CauldronInteraction { + map1.put(Items.YELLOW_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); + Map map2 = CauldronInteraction.LAVA.map(); + +- map2.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ map2.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + return CauldronInteraction.fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.LAVA_BUCKET), (iblockdata1) -> { + return true; +- }, SoundEvents.BUCKET_FILL_LAVA); ++ }, SoundEvents.BUCKET_FILL_LAVA, hitDirection); // Paper - add hitDirection + }); + CauldronInteraction.addDefaultInteractions(map2); + Map map3 = CauldronInteraction.POWDER_SNOW.map(); + +- map3.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ map3.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + return CauldronInteraction.fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.POWDER_SNOW_BUCKET), (iblockdata1) -> { + return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3; + }, SoundEvents.BUCKET_FILL_POWDER_SNOW); +@@ -217,10 +217,24 @@ public interface CauldronInteraction { + } + + static ItemInteractionResult fillBucket(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, ItemStack output, Predicate fullPredicate, SoundEvent soundEvent) { ++ // Paper start - add hitDirection ++ return fillBucket(state, world, pos, player, hand, stack, output, fullPredicate, soundEvent, null); // Paper - add hitDirection ++ } ++ static ItemInteractionResult fillBucket(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, ItemStack output, Predicate fullPredicate, SoundEvent soundEvent, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) { ++ // Paper end - add hitDirection + if (!fullPredicate.test(state)) { + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } else { + if (!world.isClientSide) { ++ // Paper start - fire PlayerBucketFillEvent ++ if (hitDirection != null) { ++ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent((net.minecraft.server.level.ServerLevel) world, player, pos, pos, hitDirection, stack, output.getItem(), hand); ++ if (event.isCancelled()) { ++ return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; ++ } ++ output = event.getItemStack() != null ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack()) : ItemStack.EMPTY; ++ } ++ // Paper end - fire PlayerBucketFillEvent + // CraftBukkit start + if (!LayeredCauldronBlock.changeLevel(state, world, pos, Blocks.CAULDRON.defaultBlockState(), player, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL, false)) { // Paper - Call CauldronLevelChangeEvent + return ItemInteractionResult.SUCCESS; +@@ -241,7 +255,22 @@ public interface CauldronInteraction { + } + + static ItemInteractionResult emptyBucket(Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, BlockState state, SoundEvent soundEvent) { ++ // Paper start - add hitDirection ++ return emptyBucket(world, pos, player, hand, stack, state, soundEvent, null); ++ } ++ static ItemInteractionResult emptyBucket(Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, BlockState state, SoundEvent soundEvent, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) { ++ // Paper end - add hitDirection + if (!world.isClientSide) { ++ // Paper start - fire PlayerBucketEmptyEvent ++ ItemStack output = new ItemStack(Items.BUCKET); ++ if (hitDirection != null) { ++ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent((net.minecraft.server.level.ServerLevel) world, player, pos, pos, hitDirection, stack, hand); ++ if (event.isCancelled()) { ++ return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; ++ } ++ output = event.getItemStack() != null ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack()) : ItemStack.EMPTY; ++ } ++ // Paper end - fire PlayerBucketEmptyEvent + // CraftBukkit start + if (!LayeredCauldronBlock.changeLevel(state, world, pos, state, player, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY, false)) { // Paper - Call CauldronLevelChangeEvent + return ItemInteractionResult.SUCCESS; +@@ -249,7 +278,7 @@ public interface CauldronInteraction { + // CraftBukkit end + Item item = stack.getItem(); + +- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.BUCKET))); ++ player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, output)); // Paper + player.awardStat(Stats.FILL_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); + // world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit +@@ -267,16 +296,16 @@ public interface CauldronInteraction { + CauldronInteraction.InteractionMap WATER = CauldronInteraction.newInteractionMap("water"); + CauldronInteraction.InteractionMap LAVA = CauldronInteraction.newInteractionMap("lava"); + CauldronInteraction.InteractionMap POWDER_SNOW = CauldronInteraction.newInteractionMap("powder_snow"); +- CauldronInteraction FILL_WATER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { +- return CauldronInteraction.emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY); ++ CauldronInteraction FILL_WATER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection ++ return CauldronInteraction.emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY, hitDirection); // Paper - add hitDirection + }; +- CauldronInteraction FILL_LAVA = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { +- return CauldronInteraction.emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA); ++ CauldronInteraction FILL_LAVA = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection ++ return CauldronInteraction.emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA, hitDirection); // Paper - add hitDirection + }; +- CauldronInteraction FILL_POWDER_SNOW = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ CauldronInteraction FILL_POWDER_SNOW = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + return CauldronInteraction.emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (BlockState) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW); + }; +- CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection + // CraftBukkit end + Block block = Block.byItem(itemstack.getItem()); + +@@ -299,7 +328,7 @@ public interface CauldronInteraction { + return ItemInteractionResult.sidedSuccess(world.isClientSide); + } + }; +- CauldronInteraction BANNER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error ++ CauldronInteraction BANNER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // CraftBukkit - decompile error // Paper - add hitDirection + BannerPatternLayers bannerpatternlayers = (BannerPatternLayers) itemstack.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY); + + if (bannerpatternlayers.layers().isEmpty()) { +@@ -322,7 +351,7 @@ public interface CauldronInteraction { + return ItemInteractionResult.sidedSuccess(world.isClientSide); + } + }; +- CauldronInteraction DYED_ITEM = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error ++ CauldronInteraction DYED_ITEM = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // CraftBukkit - decompile error // Paper - add hitDirection + if (!itemstack.is(ItemTags.DYEABLE)) { + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } else if (!itemstack.has(DataComponents.DYED_COLOR)) { +diff --git a/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java +index 20f2b575c8131621edea0e75fbf38a9fe20a36c4..4fdef6d7bcea0cf6b7d90324398af597660c80e3 100644 +--- a/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java +@@ -58,7 +58,7 @@ public abstract class AbstractCauldronBlock extends Block { + ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit + ) { + CauldronInteraction cauldronInteraction = this.interactions.map().get(stack.getItem()); +- return cauldronInteraction.interact(state, world, pos, player, hand, stack); ++ return cauldronInteraction.interact(state, world, pos, player, hand, stack, hit.getDirection()); // Paper - pass hit direction + } + + @Override