--- a/net/minecraft/world/level/block/BlockButtonAbstract.java
+++ b/net/minecraft/world/level/block/BlockButtonAbstract.java
@@ -33,6 +33,11 @@
 import net.minecraft.world.phys.shapes.VoxelShape;
 import net.minecraft.world.phys.shapes.VoxelShapeCollision;
 
+// CraftBukkit start
+import org.bukkit.event.block.BlockRedstoneEvent;
+import org.bukkit.event.entity.EntityInteractEvent;
+// CraftBukkit end
+
 public class BlockButtonAbstract extends BlockAttachable {
 
     public static final MapCodec<BlockButtonAbstract> CODEC = RecordCodecBuilder.mapCodec((instance) -> {
@@ -124,6 +129,19 @@
         if ((Boolean) iblockdata.getValue(BlockButtonAbstract.POWERED)) {
             return EnumInteractionResult.CONSUME;
         } else {
+            // CraftBukkit start
+            boolean powered = ((Boolean) iblockdata.getValue(POWERED));
+            org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
+            int old = (powered) ? 15 : 0;
+            int current = (!powered) ? 15 : 0;
+
+            BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current);
+            world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+            if ((eventRedstone.getNewCurrent() > 0) != (!powered)) {
+                return EnumInteractionResult.SUCCESS;
+            }
+            // CraftBukkit end
             this.press(iblockdata, world, blockposition);
             this.playSound(entityhuman, world, blockposition, true);
             world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_ACTIVATE, blockposition);
@@ -195,11 +213,36 @@
     }
 
     protected void checkPressed(IBlockData iblockdata, World world, BlockPosition blockposition) {
-        EntityArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (EntityArrow) world.getEntitiesOfClass(EntityArrow.class, iblockdata.getShape(world, blockposition).bounds().move(blockposition)).stream().findFirst().orElse((Object) null) : null;
+        EntityArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (EntityArrow) world.getEntitiesOfClass(EntityArrow.class, iblockdata.getShape(world, blockposition).bounds().move(blockposition)).stream().findFirst().orElse(null) : null; // CraftBukkit - decompile error
         boolean flag = entityarrow != null;
         boolean flag1 = (Boolean) iblockdata.getValue(BlockButtonAbstract.POWERED);
 
+        // CraftBukkit start - Call interact event when arrows turn on wooden buttons
+        if (flag1 != flag && flag) {
+            org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
+            EntityInteractEvent event = new EntityInteractEvent(entityarrow.getBukkitEntity(), block);
+            world.getCraftServer().getPluginManager().callEvent(event);
+
+            if (event.isCancelled()) {
+                return;
+            }
+        }
+        // CraftBukkit end
+
         if (flag != flag1) {
+            // CraftBukkit start
+            boolean powered = flag1;
+            org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
+            int old = (powered) ? 15 : 0;
+            int current = (!powered) ? 15 : 0;
+
+            BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current);
+            world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+            if ((flag && eventRedstone.getNewCurrent() <= 0) || (!flag && eventRedstone.getNewCurrent() > 0)) {
+                return;
+            }
+            // CraftBukkit end
             world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockButtonAbstract.POWERED, flag), 3);
             this.updateNeighbours(iblockdata, world, blockposition);
             this.playSound((EntityHuman) null, world, blockposition, flag);
