--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -7,6 +7,7 @@
 import net.minecraft.sounds.SoundSource;
 import net.minecraft.world.InteractionHand;
 import net.minecraft.world.InteractionResult;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.item.context.BlockPlaceContext;
 import net.minecraft.world.level.BlockGetter;
@@ -20,6 +21,7 @@
 import net.minecraft.world.level.block.state.properties.EnumProperty;
 import net.minecraft.world.level.block.state.properties.Half;
 import net.minecraft.world.level.gameevent.GameEvent;
+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.material.Material;
@@ -27,8 +29,10 @@
 import net.minecraft.world.phys.BlockHitResult;
 import net.minecraft.world.phys.shapes.CollisionContext;
 import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
 
 public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock {
+
     public static final BooleanProperty OPEN = BlockStateProperties.OPEN;
     public static final EnumProperty<Half> HALF = BlockStateProperties.HALF;
     public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
@@ -45,26 +49,26 @@
 
     protected TrapDoorBlock(BlockBehaviour.Properties settings, SoundEvent closeSound, SoundEvent openSound) {
         super(settings);
-        this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(OPEN, Boolean.valueOf(false)).setValue(HALF, Half.BOTTOM).setValue(POWERED, Boolean.valueOf(false)).setValue(WATERLOGGED, Boolean.valueOf(false)));
+        this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(TrapDoorBlock.FACING, Direction.NORTH)).setValue(TrapDoorBlock.OPEN, false)).setValue(TrapDoorBlock.HALF, Half.BOTTOM)).setValue(TrapDoorBlock.POWERED, false)).setValue(TrapDoorBlock.WATERLOGGED, false));
         this.closeSound = closeSound;
         this.openSound = openSound;
     }
 
     @Override
     public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
-        if (!state.getValue(OPEN)) {
-            return state.getValue(HALF) == Half.TOP ? TOP_AABB : BOTTOM_AABB;
+        if (!(Boolean) state.getValue(TrapDoorBlock.OPEN)) {
+            return state.getValue(TrapDoorBlock.HALF) == Half.TOP ? TrapDoorBlock.TOP_AABB : TrapDoorBlock.BOTTOM_AABB;
         } else {
-            switch ((Direction)state.getValue(FACING)) {
+            switch ((Direction) state.getValue(TrapDoorBlock.FACING)) {
                 case NORTH:
                 default:
-                    return NORTH_OPEN_AABB;
+                    return TrapDoorBlock.NORTH_OPEN_AABB;
                 case SOUTH:
-                    return SOUTH_OPEN_AABB;
+                    return TrapDoorBlock.SOUTH_OPEN_AABB;
                 case WEST:
-                    return WEST_OPEN_AABB;
+                    return TrapDoorBlock.WEST_OPEN_AABB;
                 case EAST:
-                    return EAST_OPEN_AABB;
+                    return TrapDoorBlock.EAST_OPEN_AABB;
             }
         }
     }
@@ -73,11 +77,11 @@
     public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
         switch (type) {
             case LAND:
-                return state.getValue(OPEN);
+                return (Boolean) state.getValue(TrapDoorBlock.OPEN);
             case WATER:
-                return state.getValue(WATERLOGGED);
+                return (Boolean) state.getValue(TrapDoorBlock.WATERLOGGED);
             case AIR:
-                return state.getValue(OPEN);
+                return (Boolean) state.getValue(TrapDoorBlock.OPEN);
             default:
                 return false;
         }
@@ -88,35 +92,49 @@
         if (this.material == Material.METAL) {
             return InteractionResult.PASS;
         } else {
-            state = state.cycle(OPEN);
+            state = (BlockState) state.cycle(TrapDoorBlock.OPEN);
             world.setBlock(pos, state, 2);
-            if (state.getValue(WATERLOGGED)) {
-                world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
+            if ((Boolean) state.getValue(TrapDoorBlock.WATERLOGGED)) {
+                world.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(world));
             }
 
-            this.playSound(player, world, pos, state.getValue(OPEN));
+            this.playSound(player, world, pos, (Boolean) state.getValue(TrapDoorBlock.OPEN));
             return InteractionResult.sidedSuccess(world.isClientSide);
         }
     }
 
     protected void playSound(@Nullable Player player, Level world, BlockPos pos, boolean open) {
         world.playSound(player, pos, open ? this.openSound : this.closeSound, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.1F + 0.9F);
-        world.gameEvent(player, open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos);
+        world.gameEvent((Entity) player, open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos);
     }
 
     @Override
     public void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
         if (!world.isClientSide) {
-            boolean bl = world.hasNeighborSignal(pos);
-            if (bl != state.getValue(POWERED)) {
-                if (state.getValue(OPEN) != bl) {
-                    state = state.setValue(OPEN, Boolean.valueOf(bl));
-                    this.playSound((Player)null, world, pos, bl);
+            boolean flag1 = world.hasNeighborSignal(pos);
+
+            if (flag1 != (Boolean) state.getValue(TrapDoorBlock.POWERED)) {
+                // CraftBukkit start
+                org.bukkit.World bworld = world.getWorld();
+                org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+
+                int power = bblock.getBlockPower();
+                int oldPower = (Boolean) state.getValue(OPEN) ? 15 : 0;
+
+                if (oldPower == 0 ^ power == 0 || sourceBlock.defaultBlockState().isSignalSource()) {
+                    BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bblock, oldPower, power);
+                    world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+                    flag1 = eventRedstone.getNewCurrent() > 0;
+                }
+                // CraftBukkit end
+                if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) {
+                    state = (BlockState) state.setValue(TrapDoorBlock.OPEN, flag1);
+                    this.playSound((Player) null, world, pos, flag1);
                 }
 
-                world.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(bl)), 2);
-                if (state.getValue(WATERLOGGED)) {
-                    world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
+                world.setBlock(pos, (BlockState) state.setValue(TrapDoorBlock.POWERED, flag1), 2);
+                if ((Boolean) state.getValue(TrapDoorBlock.WATERLOGGED)) {
+                    world.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(world));
                 }
             }
 
@@ -125,36 +143,37 @@
 
     @Override
     public BlockState getStateForPlacement(BlockPlaceContext ctx) {
-        BlockState blockState = this.defaultBlockState();
-        FluidState fluidState = ctx.getLevel().getFluidState(ctx.getClickedPos());
-        Direction direction = ctx.getClickedFace();
-        if (!ctx.replacingClickedOnBlock() && direction.getAxis().isHorizontal()) {
-            blockState = blockState.setValue(FACING, direction).setValue(HALF, ctx.getClickLocation().y - (double)ctx.getClickedPos().getY() > 0.5D ? Half.TOP : Half.BOTTOM);
+        BlockState iblockdata = this.defaultBlockState();
+        FluidState fluid = ctx.getLevel().getFluidState(ctx.getClickedPos());
+        Direction enumdirection = ctx.getClickedFace();
+
+        if (!ctx.replacingClickedOnBlock() && enumdirection.getAxis().isHorizontal()) {
+            iblockdata = (BlockState) ((BlockState) iblockdata.setValue(TrapDoorBlock.FACING, enumdirection)).setValue(TrapDoorBlock.HALF, ctx.getClickLocation().y - (double) ctx.getClickedPos().getY() > 0.5D ? Half.TOP : Half.BOTTOM);
         } else {
-            blockState = blockState.setValue(FACING, ctx.getHorizontalDirection().getOpposite()).setValue(HALF, direction == Direction.UP ? Half.BOTTOM : Half.TOP);
+            iblockdata = (BlockState) ((BlockState) iblockdata.setValue(TrapDoorBlock.FACING, ctx.getHorizontalDirection().getOpposite())).setValue(TrapDoorBlock.HALF, enumdirection == Direction.UP ? Half.BOTTOM : Half.TOP);
         }
 
         if (ctx.getLevel().hasNeighborSignal(ctx.getClickedPos())) {
-            blockState = blockState.setValue(OPEN, Boolean.valueOf(true)).setValue(POWERED, Boolean.valueOf(true));
+            iblockdata = (BlockState) ((BlockState) iblockdata.setValue(TrapDoorBlock.OPEN, true)).setValue(TrapDoorBlock.POWERED, true);
         }
 
-        return blockState.setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER));
+        return (BlockState) iblockdata.setValue(TrapDoorBlock.WATERLOGGED, fluid.getType() == Fluids.WATER);
     }
 
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
-        builder.add(FACING, OPEN, HALF, POWERED, WATERLOGGED);
+        builder.add(TrapDoorBlock.FACING, TrapDoorBlock.OPEN, TrapDoorBlock.HALF, TrapDoorBlock.POWERED, TrapDoorBlock.WATERLOGGED);
     }
 
     @Override
     public FluidState getFluidState(BlockState state) {
-        return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
+        return (Boolean) state.getValue(TrapDoorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
     }
 
     @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(TrapDoorBlock.WATERLOGGED)) {
+            world.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(world));
         }
 
         return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
