From dfe157971566cb8b8045f98618a3fdd584071f1b Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 1 May 2023 18:31:26 -0700
Subject: [PATCH] Break redstone on top of trap doors early

This logic hooks into the neighbour update which should be invoked
as a result of redstone powering the trap door.
---
 .../level/block/TrapDoorBlock.java.patch      | 25 +++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/TrapDoorBlock.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/TrapDoorBlock.java.patch
index d4f9fb41ee..0f858bdcd3 100644
--- a/paper-server/patches/sources/net/minecraft/world/level/block/TrapDoorBlock.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/level/block/TrapDoorBlock.java.patch
@@ -8,10 +8,11 @@
  
  public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock {
  
-@@ -143,6 +144,19 @@
+@@ -143,7 +144,39 @@
              boolean flag1 = world.hasNeighborSignal(pos);
  
              if (flag1 != (Boolean) state.getValue(TrapDoorBlock.POWERED)) {
+-                if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) {
 +                // CraftBukkit start
 +                org.bukkit.World bworld = world.getWorld();
 +                org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
@@ -25,6 +26,26 @@
 +                    flag1 = eventRedstone.getNewCurrent() > 0;
 +                }
 +                // CraftBukkit end
-                 if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) {
++                // Paper start - break redstone on trapdoors early
++                boolean open = (Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1;
++                // 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 (flag1 && 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 = world.getBlockState(abovePos);
++                    if (above.getBlock() instanceof RedStoneWireBlock) {
++                        world.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
++                        Block.popResource(world, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
++                        // now check that this didn't change our state
++                        if (world.getBlockState(pos) != state) {
++                            // our state was changed, so we cannot propagate this update
++                            return;
++                        }
++                    }
++                }
++                if (open) {
++                // Paper end - break redstone on trapdoors early
                      state = (BlockState) state.setValue(TrapDoorBlock.OPEN, flag1);
                      this.playSound((Player) null, world, pos, flag1);
+                 }