--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -146,7 +_,40 @@
         if (!level.isClientSide) {
             boolean hasNeighborSignal = level.hasNeighborSignal(pos);
             if (hasNeighborSignal != state.getValue(POWERED)) {
-                if (state.getValue(OPEN) != hasNeighborSignal) {
+                // if (state.getValue(OPEN) != hasNeighborSignal) {
+                // CraftBukkit start
+                org.bukkit.World bworld = level.getWorld();
+                org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+
+                int power = bblock.getBlockPower();
+                int oldPower = state.getValue(TrapDoorBlock.OPEN) ? 15 : 0;
+
+                if (oldPower == 0 ^ power == 0 || neighborBlock.defaultBlockState().isSignalSource()) {
+                    org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bblock, oldPower, power);
+                    level.getCraftServer().getPluginManager().callEvent(eventRedstone);
+                    hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
+                }
+                // CraftBukkit end
+                // Paper start - break redstone on trapdoors early
+                boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal;
+                // note: this must run before any state for this block/its neighborus are written to the world
+                // we allow the redstone event to fire so that plugins can block
+                if (hasNeighborSignal && open) { // if we are now powered and it caused the trap door to open
+                    // in this case, first check for the redstone on top first
+                    BlockPos abovePos = pos.above();
+                    BlockState above = level.getBlockState(abovePos);
+                    if (above.getBlock() instanceof RedStoneWireBlock) {
+                        level.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
+                        Block.popResource(level, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
+                        // now check that this didn't change our state
+                        if (level.getBlockState(pos) != state) {
+                            // our state was changed, so we cannot propagate this update
+                            return;
+                        }
+                    }
+                }
+                if (open) {
+                // Paper end - break redstone on trapdoors early
                     state = state.setValue(OPEN, Boolean.valueOf(hasNeighborSignal));
                     this.playSound(null, level, pos, hasNeighborSignal);
                 }
