--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -31,13 +31,19 @@
 import net.minecraft.world.level.block.state.properties.SculkSensorPhase;
 import net.minecraft.world.level.gameevent.GameEvent;
 import net.minecraft.world.level.gameevent.GameEventListener;
+import net.minecraft.world.level.material.Fluid;
 import net.minecraft.world.level.material.FluidState;
 import net.minecraft.world.level.material.Fluids;
 import net.minecraft.world.level.pathfinder.PathComputationType;
 import net.minecraft.world.phys.shapes.CollisionContext;
 import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.craftbukkit.v1_19_R2.block.CraftBlock;
+import org.bukkit.event.block.BlockRedstoneEvent;
+// CraftBukkit end
 
 public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterloggedBlock {
+
     public static final int ACTIVE_TICKS = 40;
     public static final int COOLDOWN_TICKS = 1;
     public static final EnumProperty<SculkSensorPhase> PHASE = BlockStateProperties.SCULK_SENSOR_PHASE;
@@ -48,7 +54,7 @@
 
     public SculkSensorBlock(BlockBehaviour.Properties settings, int range) {
         super(settings);
-        this.registerDefaultState(this.stateDefinition.any().setValue(PHASE, SculkSensorPhase.INACTIVE).setValue(POWER, Integer.valueOf(0)).setValue(WATERLOGGED, Boolean.valueOf(false)));
+        this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE)).setValue(SculkSensorBlock.POWER, 0)).setValue(SculkSensorBlock.WATERLOGGED, false));
         this.listenerRange = range;
     }
 
@@ -59,37 +65,53 @@
     @Nullable
     @Override
     public BlockState getStateForPlacement(BlockPlaceContext ctx) {
-        BlockPos blockPos = ctx.getClickedPos();
-        FluidState fluidState = ctx.getLevel().getFluidState(blockPos);
-        return this.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER));
+        BlockPos blockposition = ctx.getClickedPos();
+        FluidState fluid = ctx.getLevel().getFluidState(blockposition);
+
+        return (BlockState) this.defaultBlockState().setValue(SculkSensorBlock.WATERLOGGED, fluid.getType() == Fluids.WATER);
     }
 
     @Override
     public FluidState getFluidState(BlockState state) {
-        return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
+        return (Boolean) state.getValue(SculkSensorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
     }
 
     @Override
     public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
-        if (getPhase(state) != SculkSensorPhase.ACTIVE) {
-            if (getPhase(state) == SculkSensorPhase.COOLDOWN) {
-                world.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.INACTIVE), 3);
+        if (SculkSensorBlock.getPhase(state) != SculkSensorPhase.ACTIVE) {
+            if (SculkSensorBlock.getPhase(state) == SculkSensorPhase.COOLDOWN) {
+                world.setBlock(pos, (BlockState) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE), 3);
             }
 
         } else {
-            deactivate(world, pos, state);
+            SculkSensorBlock.deactivate(world, pos, state);
         }
     }
 
     @Override
     public void stepOn(Level world, BlockPos pos, BlockState state, Entity entity) {
-        if (!world.isClientSide() && canActivate(state) && entity.getType() != EntityType.WARDEN) {
-            BlockEntity blockEntity = world.getBlockEntity(pos);
-            if (blockEntity instanceof SculkSensorBlockEntity) {
-                SculkSensorBlockEntity sculkSensorBlockEntity = (SculkSensorBlockEntity)blockEntity;
+        if (!world.isClientSide() && SculkSensorBlock.canActivate(state) && entity.getType() != EntityType.WARDEN) {
+            // CraftBukkit start
+            org.bukkit.event.Cancellable cancellable;
+            if (entity instanceof Player) {
+                cancellable = org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+            } else {
+                cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+                world.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+            }
+            if (cancellable.isCancelled()) {
+                return;
+            }
+            // CraftBukkit end
+            BlockEntity tileentity = world.getBlockEntity(pos);
+
+            if (tileentity instanceof SculkSensorBlockEntity) {
+                SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) tileentity;
+
                 if (world instanceof ServerLevel) {
-                    ServerLevel serverLevel = (ServerLevel)world;
-                    sculkSensorBlockEntity.getListener().forceGameEvent(serverLevel, GameEvent.STEP, GameEvent.Context.of(entity), entity.position());
+                    ServerLevel worldserver = (ServerLevel) world;
+
+                    sculksensorblockentity.getListener().forceGameEvent(worldserver, GameEvent.STEP, GameEvent.Context.of(entity), entity.position());
                 }
             }
         }
@@ -100,8 +122,8 @@
     @Override
     public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
         if (!world.isClientSide() && !state.is(oldState.getBlock())) {
-            if (state.getValue(POWER) > 0 && !world.getBlockTicks().hasScheduledTick(pos, this)) {
-                world.setBlock(pos, state.setValue(POWER, Integer.valueOf(0)), 18);
+            if ((Integer) state.getValue(SculkSensorBlock.POWER) > 0 && !world.getBlockTicks().hasScheduledTick(pos, this)) {
+                world.setBlock(pos, (BlockState) state.setValue(SculkSensorBlock.POWER, 0), 18);
             }
 
             world.scheduleTick(new BlockPos(pos), state.getBlock(), 1);
@@ -111,8 +133,8 @@
     @Override
     public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
         if (!state.is(newState.getBlock())) {
-            if (getPhase(state) == SculkSensorPhase.ACTIVE) {
-                updateNeighbours(world, pos);
+            if (SculkSensorBlock.getPhase(state) == SculkSensorPhase.ACTIVE) {
+                SculkSensorBlock.updateNeighbours(world, pos);
             }
 
             super.onRemove(state, world, pos, newState, moved);
@@ -121,8 +143,8 @@
 
     @Override
     public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
-        if (state.getValue(WATERLOGGED)) {
-            world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
+        if ((Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) {
+            world.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(world));
         }
 
         return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -142,14 +164,14 @@
     @Nullable
     @Override
     public <T extends BlockEntity> GameEventListener getListener(ServerLevel world, T blockEntity) {
-        return blockEntity instanceof SculkSensorBlockEntity ? ((SculkSensorBlockEntity)blockEntity).getListener() : null;
+        return blockEntity instanceof SculkSensorBlockEntity ? ((SculkSensorBlockEntity) blockEntity).getListener() : null;
     }
 
     @Nullable
     @Override
     public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level world, BlockState state, BlockEntityType<T> type) {
-        return !world.isClientSide ? createTickerHelper(type, BlockEntityType.SCULK_SENSOR, (worldx, pos, statex, blockEntity) -> {
-            blockEntity.getListener().tick(worldx);
+        return !world.isClientSide ? createTickerHelper(type, BlockEntityType.SCULK_SENSOR, (world1, blockposition, iblockdata1, sculksensorblockentity) -> {
+            sculksensorblockentity.getListener().tick(world1);
         }) : null;
     }
 
@@ -160,7 +182,7 @@
 
     @Override
     public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
-        return SHAPE;
+        return SculkSensorBlock.SHAPE;
     }
 
     @Override
@@ -170,55 +192,75 @@
 
     @Override
     public int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) {
-        return state.getValue(POWER);
+        return (Integer) state.getValue(SculkSensorBlock.POWER);
     }
 
     public static SculkSensorPhase getPhase(BlockState state) {
-        return state.getValue(PHASE);
+        return (SculkSensorPhase) state.getValue(SculkSensorBlock.PHASE);
     }
 
     public static boolean canActivate(BlockState state) {
-        return getPhase(state) == SculkSensorPhase.INACTIVE;
+        return SculkSensorBlock.getPhase(state) == SculkSensorPhase.INACTIVE;
     }
 
     public static void deactivate(Level world, BlockPos pos, BlockState state) {
-        world.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.COOLDOWN).setValue(POWER, Integer.valueOf(0)), 3);
+        // CraftBukkit start
+        BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, pos), state.getValue(SculkSensorBlock.POWER), 0);
+        world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+        if (eventRedstone.getNewCurrent() > 0) {
+            world.setBlock(pos, state.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3);
+            return;
+        }
+        // CraftBukkit end
+        world.setBlock(pos, (BlockState) ((BlockState) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3);
         world.scheduleTick(pos, state.getBlock(), 1);
-        if (!state.getValue(WATERLOGGED)) {
-            world.playSound((Player)null, pos, SoundEvents.SCULK_CLICKING_STOP, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.2F + 0.8F);
+        if (!(Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) {
+            world.playSound((Player) null, pos, SoundEvents.SCULK_CLICKING_STOP, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.2F + 0.8F);
         }
 
-        updateNeighbours(world, pos);
+        SculkSensorBlock.updateNeighbours(world, pos);
     }
 
     public static void activate(@Nullable Entity entity, Level world, BlockPos pos, BlockState state, int power) {
-        world.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.ACTIVE).setValue(POWER, Integer.valueOf(power)), 3);
+        // CraftBukkit start
+        BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, pos), state.getValue(SculkSensorBlock.POWER), power);
+        world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+        if (eventRedstone.getNewCurrent() <= 0) {
+            return;
+        }
+        power = eventRedstone.getNewCurrent();
+        // CraftBukkit end
+        world.setBlock(pos, (BlockState) ((BlockState) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, power), 3);
         world.scheduleTick(pos, state.getBlock(), 40);
-        updateNeighbours(world, pos);
+        SculkSensorBlock.updateNeighbours(world, pos);
         world.gameEvent(entity, GameEvent.SCULK_SENSOR_TENDRILS_CLICKING, pos);
-        if (!state.getValue(WATERLOGGED)) {
-            world.playSound((Player)null, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, SoundEvents.SCULK_CLICKING, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.2F + 0.8F);
+        if (!(Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) {
+            world.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.SCULK_CLICKING, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.2F + 0.8F);
         }
 
     }
 
     @Override
     public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
-        if (getPhase(state) == SculkSensorPhase.ACTIVE) {
-            Direction direction = Direction.getRandom(random);
-            if (direction != Direction.UP && direction != Direction.DOWN) {
-                double d = (double)pos.getX() + 0.5D + (direction.getStepX() == 0 ? 0.5D - random.nextDouble() : (double)direction.getStepX() * 0.6D);
-                double e = (double)pos.getY() + 0.25D;
-                double f = (double)pos.getZ() + 0.5D + (direction.getStepZ() == 0 ? 0.5D - random.nextDouble() : (double)direction.getStepZ() * 0.6D);
-                double g = (double)random.nextFloat() * 0.04D;
-                world.addParticle(DustColorTransitionOptions.SCULK_TO_REDSTONE, d, e, f, 0.0D, g, 0.0D);
+        if (SculkSensorBlock.getPhase(state) == SculkSensorPhase.ACTIVE) {
+            Direction enumdirection = Direction.getRandom(random);
+
+            if (enumdirection != Direction.UP && enumdirection != Direction.DOWN) {
+                double d0 = (double) pos.getX() + 0.5D + (enumdirection.getStepX() == 0 ? 0.5D - random.nextDouble() : (double) enumdirection.getStepX() * 0.6D);
+                double d1 = (double) pos.getY() + 0.25D;
+                double d2 = (double) pos.getZ() + 0.5D + (enumdirection.getStepZ() == 0 ? 0.5D - random.nextDouble() : (double) enumdirection.getStepZ() * 0.6D);
+                double d3 = (double) random.nextFloat() * 0.04D;
+
+                world.addParticle(DustColorTransitionOptions.SCULK_TO_REDSTONE, d0, d1, d2, 0.0D, d3, 0.0D);
             }
         }
     }
 
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
-        builder.add(PHASE, POWER, WATERLOGGED);
+        builder.add(SculkSensorBlock.PHASE, SculkSensorBlock.POWER, SculkSensorBlock.WATERLOGGED);
     }
 
     @Override
@@ -228,9 +270,12 @@
 
     @Override
     public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) {
-        BlockEntity blockEntity = world.getBlockEntity(pos);
-        if (blockEntity instanceof SculkSensorBlockEntity sculkSensorBlockEntity) {
-            return getPhase(state) == SculkSensorPhase.ACTIVE ? sculkSensorBlockEntity.getLastVibrationFrequency() : 0;
+        BlockEntity tileentity = world.getBlockEntity(pos);
+
+        if (tileentity instanceof SculkSensorBlockEntity) {
+            SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) tileentity;
+
+            return SculkSensorBlock.getPhase(state) == SculkSensorPhase.ACTIVE ? sculksensorblockentity.getLastVibrationFrequency() : 0;
         } else {
             return 0;
         }
@@ -249,9 +294,16 @@
     @Override
     public void spawnAfterBreak(BlockState state, ServerLevel world, BlockPos pos, ItemStack stack, boolean dropExperience) {
         super.spawnAfterBreak(state, world, pos, stack, dropExperience);
-        if (dropExperience) {
-            this.tryDropExperience(world, pos, stack, ConstantInt.of(5));
+        // CraftBukkit start - Delegate to getExpDrop
+    }
+
+    @Override
+    public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+        if (flag) {
+            return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5));
         }
 
+        return 0;
+        // CraftBukkit end
     }
 }
