From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 9 Aug 2021 20:45:46 -0700
Subject: [PATCH] Fire EntityChangeBlockEvent in more places

Co-authored-by: ChristopheG <61288881+chrisgdt@users.noreply.github.com>

diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java
index 534ff7d4844448eaddb2778f81dfd66d1ee375db..558c14af6415681909f9e3a15f303ce4d0ec1395 100644
--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java
+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java
@@ -98,7 +98,7 @@ public class LightningBolt extends Entity {
                 }
 
                 this.powerLightningRod();
-                LightningBolt.clearCopperOnLightningStrike(this.level, this.getStrikePosition());
+                LightningBolt.clearCopperOnLightningStrike(this.level, this.getStrikePosition(), this); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
                 this.gameEvent(GameEvent.LIGHTNING_STRIKE);
             }
         }
@@ -192,7 +192,7 @@ public class LightningBolt extends Entity {
         }
     }
 
-    private static void clearCopperOnLightningStrike(Level world, BlockPos pos) {
+    private static void clearCopperOnLightningStrike(Level world, BlockPos pos, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
         BlockState iblockdata = world.getBlockState(pos);
         BlockPos blockposition1;
         BlockState iblockdata1;
@@ -206,24 +206,29 @@ public class LightningBolt extends Entity {
         }
 
         if (iblockdata1.getBlock() instanceof WeatheringCopper) {
-            world.setBlockAndUpdate(blockposition1, WeatheringCopper.getFirst(world.getBlockState(blockposition1)));
+            // Paper start - call EntityChangeBlockEvent
+            BlockState newBlock = WeatheringCopper.getFirst(world.getBlockState(blockposition1));
+            if (!CraftEventFactory.callEntityChangeBlockEvent(lightning, blockposition1, newBlock).isCancelled()) {
+                world.setBlockAndUpdate(blockposition1, newBlock);
+            }
+            // Paper end
             BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable();
             int i = world.random.nextInt(3) + 3;
 
             for (int j = 0; j < i; ++j) {
                 int k = world.random.nextInt(8) + 1;
 
-                LightningBolt.randomWalkCleaningCopper(world, blockposition1, blockposition_mutableblockposition, k);
+                LightningBolt.randomWalkCleaningCopper(world, blockposition1, blockposition_mutableblockposition, k, lightning); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
             }
 
         }
     }
 
-    private static void randomWalkCleaningCopper(Level world, BlockPos pos, BlockPos.MutableBlockPos mutablePos, int count) {
+    private static void randomWalkCleaningCopper(Level world, BlockPos pos, BlockPos.MutableBlockPos mutablePos, int count, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
         mutablePos.set(pos);
 
         for (int j = 0; j < count; ++j) {
-            Optional<BlockPos> optional = LightningBolt.randomStepCleaningCopper(world, mutablePos);
+            Optional<BlockPos> optional = LightningBolt.randomStepCleaningCopper(world, mutablePos, lightning); // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
 
             if (!optional.isPresent()) {
                 break;
@@ -234,7 +239,7 @@ public class LightningBolt extends Entity {
 
     }
 
-    private static Optional<BlockPos> randomStepCleaningCopper(Level world, BlockPos pos) {
+    private static Optional<BlockPos> randomStepCleaningCopper(Level world, BlockPos pos, Entity lightning) { // Paper - transmit LightningBolt instance to call EntityChangeBlockEvent
         Iterator iterator = BlockPos.randomInCube(world.random, 10, pos, 1).iterator();
 
         BlockPos blockposition1;
@@ -251,6 +256,7 @@ public class LightningBolt extends Entity {
 
         BlockPos blockposition1Final = blockposition1; // CraftBukkit - decompile error
         WeatheringCopper.getPrevious(iblockdata).ifPresent((iblockdata1) -> {
+            if (!CraftEventFactory.callEntityChangeBlockEvent(lightning, blockposition1Final, iblockdata1).isCancelled()) // Paper - call EntityChangeBlockEvent
             world.setBlockAndUpdate(blockposition1Final, iblockdata1); // CraftBukkit - decompile error
         });
         world.levelEvent(3002, blockposition1, -1);
diff --git a/src/main/java/net/minecraft/world/item/AxeItem.java b/src/main/java/net/minecraft/world/item/AxeItem.java
index 2f8ae1786a4c4438515c59fa56acaefdff60703d..9c7d0b9cc2fa98d5785c914c0183f7d4b5b1c1ea 100644
--- a/src/main/java/net/minecraft/world/item/AxeItem.java
+++ b/src/main/java/net/minecraft/world/item/AxeItem.java
@@ -54,6 +54,11 @@ public class AxeItem extends DiggerItem {
         }
 
         if (optional4.isPresent()) {
+            // Paper start - EntityChangeBlockEvent
+            if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, optional4.get()).isCancelled()) {
+                return InteractionResult.PASS;
+            }
+            // Paper end
             if (player instanceof ServerPlayer) {
                 CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack);
             }
diff --git a/src/main/java/net/minecraft/world/item/EnderEyeItem.java b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
index e0c3aa1285709a40ff0ea8c1d74d43d2b341aecc..f4fc8ff3981555e4b560289248a9b02afc04b42f 100644
--- a/src/main/java/net/minecraft/world/item/EnderEyeItem.java
+++ b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
@@ -43,6 +43,11 @@ public class EnderEyeItem extends Item {
                 return InteractionResult.SUCCESS;
             } else {
                 BlockState iblockdata1 = (BlockState) iblockdata.setValue(EndPortalFrameBlock.HAS_EYE, true);
+                // Paper start
+                if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(context.getPlayer(), blockposition, iblockdata1).isCancelled()) {
+                    return InteractionResult.PASS;
+                }
+                // Paper end
 
                 Block.pushEntitiesUp(iblockdata, iblockdata1, world, blockposition);
                 world.setBlock(blockposition, iblockdata1, 2);
diff --git a/src/main/java/net/minecraft/world/item/HoneycombItem.java b/src/main/java/net/minecraft/world/item/HoneycombItem.java
index 68a8d3b16d49c10fc9834f32009095d35c9c55a8..f0b720eafc538f97d788f89bd2f2e9da0ff84a19 100644
--- a/src/main/java/net/minecraft/world/item/HoneycombItem.java
+++ b/src/main/java/net/minecraft/world/item/HoneycombItem.java
@@ -37,6 +37,14 @@ public class HoneycombItem extends Item {
         return getWaxed(blockState).map((state) -> {
             Player player = context.getPlayer();
             ItemStack itemStack = context.getItemInHand();
+            // Paper start - EntityChangeBlockEvent
+            if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, state).isCancelled()) {
+                if (!player.isCreative()) {
+                    player.containerMenu.sendAllDataToRemote();
+                }
+                return InteractionResult.PASS;
+            }
+            // Paper end
             if (player instanceof ServerPlayer) {
                 CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack);
             }
diff --git a/src/main/java/net/minecraft/world/item/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java
index 93bb2cbd397fef4db9d903d2b41a35b6d67bf4a9..3a6601ede6fd7caa48cdbf9856c2e72fd4e73ca8 100644
--- a/src/main/java/net/minecraft/world/item/PotionItem.java
+++ b/src/main/java/net/minecraft/world/item/PotionItem.java
@@ -107,6 +107,12 @@ public class PotionItem extends Item {
         BlockState iblockdata = world.getBlockState(blockposition);
 
         if (context.getClickedFace() != Direction.DOWN && iblockdata.is(BlockTags.CONVERTABLE_TO_MUD) && PotionUtils.getPotion(itemstack) == Potions.WATER) {
+            // Paper start
+            if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entityhuman, blockposition, Blocks.MUD.defaultBlockState()).isCancelled()) {
+                entityhuman.containerMenu.sendAllDataToRemote();
+                return InteractionResult.PASS;
+            }
+            // Paper end
             world.playSound((Player) null, blockposition, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F);
             entityhuman.setItemInHand(context.getHand(), ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE)));
             entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));
diff --git a/src/main/java/net/minecraft/world/item/ShovelItem.java b/src/main/java/net/minecraft/world/item/ShovelItem.java
index 32995cb5efdad0bc34ecacacb78cccd21220ba8d..c7195f2e12bbd6545f7bffcc2b4ba5cc3d48df20 100644
--- a/src/main/java/net/minecraft/world/item/ShovelItem.java
+++ b/src/main/java/net/minecraft/world/item/ShovelItem.java
@@ -36,20 +36,29 @@ public class ShovelItem extends DiggerItem {
             Player player = context.getPlayer();
             BlockState blockState2 = FLATTENABLES.get(blockState.getBlock());
             BlockState blockState3 = null;
+            Runnable afterAction = null; // Paper
             if (blockState2 != null && level.getBlockState(blockPos.above()).isAir()) {
-                level.playSound(player, blockPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);
+                afterAction = () -> level.playSound(player, blockPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); // Paper
                 blockState3 = blockState2;
             } else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) {
+                afterAction = () -> { // Paper
                 if (!level.isClientSide()) {
                     level.levelEvent((Player)null, 1009, blockPos, 0);
                 }
 
                 CampfireBlock.dowse(context.getPlayer(), level, blockPos, blockState);
+                }; // Paper
                 blockState3 = blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false));
             }
 
             if (blockState3 != null) {
                 if (!level.isClientSide) {
+                    // Paper start
+                    if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(context.getPlayer(), blockPos, blockState3).isCancelled()) {
+                        return InteractionResult.PASS;
+                    }
+                    afterAction.run();
+                    // Paper end
                     level.setBlock(blockPos, blockState3, 11);
                     level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(player, blockState3));
                     if (player != null) {
diff --git a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
index 53f4a000079f4c056500d03eca71991ae14483a9..e81bda56c58df6c3109382c17e86f4cc0f16cf81 100644
--- a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
@@ -229,7 +229,14 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
 
         if (i < 8 && ComposterBlock.COMPOSTABLES.containsKey(itemstack.getItem())) {
             if (i < 7 && !world.isClientSide) {
-                BlockState iblockdata1 = ComposterBlock.addItem(player, state, world, pos, itemstack);
+                // Paper start - EntityChangeBlockEvent
+                double rand = world.getRandom().nextDouble();
+                BlockState dummyBlockState = ComposterBlock.addItem(player, state, org.bukkit.craftbukkit.util.DummyGeneratorAccess.INSTANCE, pos, itemstack, rand);
+                if (state != dummyBlockState && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, dummyBlockState).isCancelled()) { // if block state will change and event cancelled
+                    return InteractionResult.sidedSuccess(world.isClientSide);
+                }
+                BlockState iblockdata1 = ComposterBlock.addItem(player, state, world, pos, itemstack, rand);
+                // Paper end
 
                 world.levelEvent(1500, pos, state != iblockdata1 ? 1 : 0);
                 player.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));
diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
index 80026dcdb66cc88a080b33ef290a6a7fb7bcbbaa..0b7d882551bcb8be149754209aad5fe4142f0fac 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
@@ -120,7 +120,7 @@ public class DummyGeneratorAccess implements WorldGenLevel {
 
     @Override
     public void gameEvent(GameEvent event, Vec3 emitterPos, GameEvent.Context emitter) {
-        // Used by BlockComposter
+        // Used by ComposterBlock
     }
 
     @Override