--- a/net/minecraft/world/level/block/ButtonBlock.java
+++ b/net/minecraft/world/level/block/ButtonBlock.java
@@ -7,6 +7,7 @@
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Direction;
+import net.minecraft.core.Holder;
 import net.minecraft.server.level.ServerLevel;
 import net.minecraft.sounds.SoundEvent;
 import net.minecraft.sounds.SoundSource;
@@ -31,97 +32,125 @@
 import net.minecraft.world.phys.BlockHitResult;
 import net.minecraft.world.phys.shapes.CollisionContext;
 import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.event.block.BlockRedstoneEvent;
+import org.bukkit.event.entity.EntityInteractEvent;
+// CraftBukkit end
 
 public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
-    public static final MapCodec<ButtonBlock> CODEC = RecordCodecBuilder.mapCodec(
-        instance -> instance.group(
-                    BlockSetType.CODEC.fieldOf("block_set_type").forGetter(block -> block.type),
-                    Codec.intRange(1, 1024).fieldOf("ticks_to_stay_pressed").forGetter(block -> block.ticksToStayPressed),
-                    propertiesCodec()
-                )
-                .apply(instance, ButtonBlock::new)
-    );
+
+    public static final MapCodec<ButtonBlock> CODEC = RecordCodecBuilder.mapCodec((instance) -> {
+        return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blockbuttonabstract) -> {
+            return blockbuttonabstract.type;
+        }), Codec.intRange(1, 1024).fieldOf("ticks_to_stay_pressed").forGetter((blockbuttonabstract) -> {
+            return blockbuttonabstract.ticksToStayPressed;
+        }), propertiesCodec()).apply(instance, ButtonBlock::new);
+    });
     public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
     private static final int PRESSED_DEPTH = 1;
     private static final int UNPRESSED_DEPTH = 2;
     protected static final int HALF_AABB_HEIGHT = 2;
     protected static final int HALF_AABB_WIDTH = 3;
-    protected static final VoxelShape CEILING_AABB_X = Block.box(6.0, 14.0, 5.0, 10.0, 16.0, 11.0);
-    protected static final VoxelShape CEILING_AABB_Z = Block.box(5.0, 14.0, 6.0, 11.0, 16.0, 10.0);
-    protected static final VoxelShape FLOOR_AABB_X = Block.box(6.0, 0.0, 5.0, 10.0, 2.0, 11.0);
-    protected static final VoxelShape FLOOR_AABB_Z = Block.box(5.0, 0.0, 6.0, 11.0, 2.0, 10.0);
-    protected static final VoxelShape NORTH_AABB = Block.box(5.0, 6.0, 14.0, 11.0, 10.0, 16.0);
-    protected static final VoxelShape SOUTH_AABB = Block.box(5.0, 6.0, 0.0, 11.0, 10.0, 2.0);
-    protected static final VoxelShape WEST_AABB = Block.box(14.0, 6.0, 5.0, 16.0, 10.0, 11.0);
-    protected static final VoxelShape EAST_AABB = Block.box(0.0, 6.0, 5.0, 2.0, 10.0, 11.0);
-    protected static final VoxelShape PRESSED_CEILING_AABB_X = Block.box(6.0, 15.0, 5.0, 10.0, 16.0, 11.0);
-    protected static final VoxelShape PRESSED_CEILING_AABB_Z = Block.box(5.0, 15.0, 6.0, 11.0, 16.0, 10.0);
-    protected static final VoxelShape PRESSED_FLOOR_AABB_X = Block.box(6.0, 0.0, 5.0, 10.0, 1.0, 11.0);
-    protected static final VoxelShape PRESSED_FLOOR_AABB_Z = Block.box(5.0, 0.0, 6.0, 11.0, 1.0, 10.0);
-    protected static final VoxelShape PRESSED_NORTH_AABB = Block.box(5.0, 6.0, 15.0, 11.0, 10.0, 16.0);
-    protected static final VoxelShape PRESSED_SOUTH_AABB = Block.box(5.0, 6.0, 0.0, 11.0, 10.0, 1.0);
-    protected static final VoxelShape PRESSED_WEST_AABB = Block.box(15.0, 6.0, 5.0, 16.0, 10.0, 11.0);
-    protected static final VoxelShape PRESSED_EAST_AABB = Block.box(0.0, 6.0, 5.0, 1.0, 10.0, 11.0);
+    protected static final VoxelShape CEILING_AABB_X = Block.box(6.0D, 14.0D, 5.0D, 10.0D, 16.0D, 11.0D);
+    protected static final VoxelShape CEILING_AABB_Z = Block.box(5.0D, 14.0D, 6.0D, 11.0D, 16.0D, 10.0D);
+    protected static final VoxelShape FLOOR_AABB_X = Block.box(6.0D, 0.0D, 5.0D, 10.0D, 2.0D, 11.0D);
+    protected static final VoxelShape FLOOR_AABB_Z = Block.box(5.0D, 0.0D, 6.0D, 11.0D, 2.0D, 10.0D);
+    protected static final VoxelShape NORTH_AABB = Block.box(5.0D, 6.0D, 14.0D, 11.0D, 10.0D, 16.0D);
+    protected static final VoxelShape SOUTH_AABB = Block.box(5.0D, 6.0D, 0.0D, 11.0D, 10.0D, 2.0D);
+    protected static final VoxelShape WEST_AABB = Block.box(14.0D, 6.0D, 5.0D, 16.0D, 10.0D, 11.0D);
+    protected static final VoxelShape EAST_AABB = Block.box(0.0D, 6.0D, 5.0D, 2.0D, 10.0D, 11.0D);
+    protected static final VoxelShape PRESSED_CEILING_AABB_X = Block.box(6.0D, 15.0D, 5.0D, 10.0D, 16.0D, 11.0D);
+    protected static final VoxelShape PRESSED_CEILING_AABB_Z = Block.box(5.0D, 15.0D, 6.0D, 11.0D, 16.0D, 10.0D);
+    protected static final VoxelShape PRESSED_FLOOR_AABB_X = Block.box(6.0D, 0.0D, 5.0D, 10.0D, 1.0D, 11.0D);
+    protected static final VoxelShape PRESSED_FLOOR_AABB_Z = Block.box(5.0D, 0.0D, 6.0D, 11.0D, 1.0D, 10.0D);
+    protected static final VoxelShape PRESSED_NORTH_AABB = Block.box(5.0D, 6.0D, 15.0D, 11.0D, 10.0D, 16.0D);
+    protected static final VoxelShape PRESSED_SOUTH_AABB = Block.box(5.0D, 6.0D, 0.0D, 11.0D, 10.0D, 1.0D);
+    protected static final VoxelShape PRESSED_WEST_AABB = Block.box(15.0D, 6.0D, 5.0D, 16.0D, 10.0D, 11.0D);
+    protected static final VoxelShape PRESSED_EAST_AABB = Block.box(0.0D, 6.0D, 5.0D, 1.0D, 10.0D, 11.0D);
     private final BlockSetType type;
     private final int ticksToStayPressed;
 
     @Override
     public MapCodec<ButtonBlock> codec() {
-        return CODEC;
+        return ButtonBlock.CODEC;
     }
 
     protected ButtonBlock(BlockSetType blockSetType, int pressTicks, BlockBehaviour.Properties settings) {
         super(settings.sound(blockSetType.soundType()));
         this.type = blockSetType;
-        this.registerDefaultState(
-            this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(POWERED, Boolean.valueOf(false)).setValue(FACE, AttachFace.WALL)
-        );
+        this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ButtonBlock.FACING, Direction.NORTH)).setValue(ButtonBlock.POWERED, false)).setValue(ButtonBlock.FACE, AttachFace.WALL));
         this.ticksToStayPressed = pressTicks;
     }
 
     @Override
     protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
-        Direction direction = state.getValue(FACING);
-        boolean bl = state.getValue(POWERED);
-        switch ((AttachFace)state.getValue(FACE)) {
+        Direction enumdirection = (Direction) state.getValue(ButtonBlock.FACING);
+        boolean flag = (Boolean) state.getValue(ButtonBlock.POWERED);
+
+        switch ((AttachFace) state.getValue(ButtonBlock.FACE)) {
             case FLOOR:
-                if (direction.getAxis() == Direction.Axis.X) {
-                    return bl ? PRESSED_FLOOR_AABB_X : FLOOR_AABB_X;
+                if (enumdirection.getAxis() == Direction.Axis.X) {
+                    return flag ? ButtonBlock.PRESSED_FLOOR_AABB_X : ButtonBlock.FLOOR_AABB_X;
                 }
 
-                return bl ? PRESSED_FLOOR_AABB_Z : FLOOR_AABB_Z;
+                return flag ? ButtonBlock.PRESSED_FLOOR_AABB_Z : ButtonBlock.FLOOR_AABB_Z;
             case WALL:
-                return switch (direction) {
-                    case EAST -> bl ? PRESSED_EAST_AABB : EAST_AABB;
-                    case WEST -> bl ? PRESSED_WEST_AABB : WEST_AABB;
-                    case SOUTH -> bl ? PRESSED_SOUTH_AABB : SOUTH_AABB;
-                    case NORTH, UP, DOWN -> bl ? PRESSED_NORTH_AABB : NORTH_AABB;
-                };
+                VoxelShape voxelshape;
+
+                switch (enumdirection) {
+                    case EAST:
+                        voxelshape = flag ? ButtonBlock.PRESSED_EAST_AABB : ButtonBlock.EAST_AABB;
+                        break;
+                    case WEST:
+                        voxelshape = flag ? ButtonBlock.PRESSED_WEST_AABB : ButtonBlock.WEST_AABB;
+                        break;
+                    case SOUTH:
+                        voxelshape = flag ? ButtonBlock.PRESSED_SOUTH_AABB : ButtonBlock.SOUTH_AABB;
+                        break;
+                    case NORTH:
+                    case UP:
+                    case DOWN:
+                        voxelshape = flag ? ButtonBlock.PRESSED_NORTH_AABB : ButtonBlock.NORTH_AABB;
+                        break;
+                    default:
+                        throw new MatchException((String) null, (Throwable) null);
+                }
+
+                return voxelshape;
             case CEILING:
             default:
-                if (direction.getAxis() == Direction.Axis.X) {
-                    return bl ? PRESSED_CEILING_AABB_X : CEILING_AABB_X;
-                } else {
-                    return bl ? PRESSED_CEILING_AABB_Z : CEILING_AABB_Z;
-                }
+                return enumdirection.getAxis() == Direction.Axis.X ? (flag ? ButtonBlock.PRESSED_CEILING_AABB_X : ButtonBlock.CEILING_AABB_X) : (flag ? ButtonBlock.PRESSED_CEILING_AABB_Z : ButtonBlock.CEILING_AABB_Z);
         }
     }
 
     @Override
     protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
-        if (state.getValue(POWERED)) {
+        if ((Boolean) state.getValue(ButtonBlock.POWERED)) {
             return InteractionResult.CONSUME;
         } else {
+            // CraftBukkit start
+            boolean powered = ((Boolean) state.getValue(ButtonBlock.POWERED));
+            org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.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 InteractionResult.SUCCESS;
+            }
+            // CraftBukkit end
             this.press(state, world, pos);
             this.playSound(player, world, pos, true);
-            world.gameEvent(player, GameEvent.BLOCK_ACTIVATE, pos);
+            world.gameEvent((Entity) player, (Holder) GameEvent.BLOCK_ACTIVATE, pos);
             return InteractionResult.sidedSuccess(world.isClientSide);
         }
     }
 
     @Override
     protected void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) {
-        if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !world.isClientSide() && !state.getValue(POWERED)) {
+        if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !world.isClientSide() && !(Boolean) state.getValue(ButtonBlock.POWERED)) {
             this.press(state, world, pos);
         }
 
@@ -129,9 +158,9 @@
     }
 
     public void press(BlockState state, Level world, BlockPos pos) {
-        world.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 3);
+        world.setBlock(pos, (BlockState) state.setValue(ButtonBlock.POWERED, true), 3);
         this.updateNeighbours(state, world, pos);
-        world.scheduleTick(pos, this, this.ticksToStayPressed);
+        world.scheduleTick(pos, (Block) this, this.ticksToStayPressed);
     }
 
     protected void playSound(@Nullable Player player, LevelAccessor world, BlockPos pos, boolean powered) {
@@ -145,7 +174,7 @@
     @Override
     protected void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
         if (!moved && !state.is(newState.getBlock())) {
-            if (state.getValue(POWERED)) {
+            if ((Boolean) state.getValue(ButtonBlock.POWERED)) {
                 this.updateNeighbours(state, world, pos);
             }
 
@@ -155,12 +184,12 @@
 
     @Override
     protected int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) {
-        return state.getValue(POWERED) ? 15 : 0;
+        return (Boolean) state.getValue(ButtonBlock.POWERED) ? 15 : 0;
     }
 
     @Override
     protected int getDirectSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) {
-        return state.getValue(POWERED) && getConnectedDirection(state) == direction ? 15 : 0;
+        return (Boolean) state.getValue(ButtonBlock.POWERED) && getConnectedDirection(state) == direction ? 15 : 0;
     }
 
     @Override
@@ -170,34 +199,60 @@
 
     @Override
     protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
-        if (state.getValue(POWERED)) {
+        if ((Boolean) state.getValue(ButtonBlock.POWERED)) {
             this.checkPressed(state, world, pos);
         }
     }
 
     @Override
     protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
-        if (!world.isClientSide && this.type.canButtonBeActivatedByArrows() && !state.getValue(POWERED)) {
+        if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
+        if (!world.isClientSide && this.type.canButtonBeActivatedByArrows() && !(Boolean) state.getValue(ButtonBlock.POWERED)) {
             this.checkPressed(state, world, pos);
         }
     }
 
     protected void checkPressed(BlockState state, Level world, BlockPos pos) {
-        AbstractArrow abstractArrow = this.type.canButtonBeActivatedByArrows()
-            ? world.getEntitiesOfClass(AbstractArrow.class, state.getShape(world, pos).bounds().move(pos)).stream().findFirst().orElse(null)
-            : null;
-        boolean bl = abstractArrow != null;
-        boolean bl2 = state.getValue(POWERED);
-        if (bl != bl2) {
-            world.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(bl)), 3);
+        AbstractArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (AbstractArrow) world.getEntitiesOfClass(AbstractArrow.class, state.getShape(world, pos).bounds().move(pos)).stream().findFirst().orElse(null) : null; // CraftBukkit - decompile error
+        boolean flag = entityarrow != null;
+        boolean flag1 = (Boolean) state.getValue(ButtonBlock.POWERED);
+
+        // CraftBukkit start - Call interact event when arrows turn on wooden buttons
+        if (flag1 != flag && flag) {
+            org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.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(pos.getX(), pos.getY(), pos.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(pos, (BlockState) state.setValue(ButtonBlock.POWERED, flag), 3);
             this.updateNeighbours(state, world, pos);
-            this.playSound(null, world, pos, bl);
-            world.gameEvent(abstractArrow, bl ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos);
+            this.playSound((Player) null, world, pos, flag);
+            world.gameEvent((Entity) entityarrow, (Holder) (flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE), pos);
         }
 
-        if (bl) {
-            world.scheduleTick(new BlockPos(pos), this, this.ticksToStayPressed);
+        if (flag) {
+            world.scheduleTick(new BlockPos(pos), (Block) this, this.ticksToStayPressed);
         }
+
     }
 
     private void updateNeighbours(BlockState state, Level world, BlockPos pos) {
@@ -207,6 +262,6 @@
 
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
-        builder.add(FACING, POWERED, FACE);
+        builder.add(ButtonBlock.FACING, ButtonBlock.POWERED, ButtonBlock.FACE);
     }
 }
