public void onPlayerInteract(PlayerInteractEvent pie) {
    if (Action.LEFT_CLICK_BLOCK.equals(pie.getAction())
        || (isValidBlock(pie.getClickedBlock())
            && Action.RIGHT_CLICK_BLOCK.equals(pie.getAction()))) {
      Block clicked = pie.getClickedBlock();
      Block behind = clicked.getRelative(pie.getBlockFace().getOppositeFace());

      SecretDoor door = null;

      if (Material.WOODEN_DOOR.equals(clicked.getType()) && !SecretDoor.isDoubleDoor(clicked)) {
        if (this.plugin.isSecretDoor(SecretDoor.getKeyFromBlock(clicked))) {
          this.plugin.closeDoor(SecretDoor.getKeyFromBlock(clicked));
        } else if (!Material.AIR.equals(behind.getType())) {
          if (SecretDoor.isAdjacentDoor(clicked, pie.getBlockFace()))
            door = new SecretDoor(clicked, behind, SecretDoor.Direction.DOOR_FIRST);
        }

      } else if (Material.WOODEN_DOOR.equals(behind.getType())
          && !SecretDoor.isDoubleDoor(behind)) {
        if (this.plugin.isSecretDoor(SecretDoor.getKeyFromBlock(behind))) {
          this.plugin.closeDoor(SecretDoor.getKeyFromBlock(behind));
        } else if (SecretDoor.isAdjacentDoor(behind, pie.getBlockFace().getOppositeFace()))
          door = new SecretDoor(behind, clicked, SecretDoor.Direction.BLOCK_FIRST);
      }

      if (!(door == null)) {
        plugin.addDoor(door).open();
        pie.getPlayer().sendMessage(ChatColor.RED + "Don't forget to close the door!");
      }
    }
  }
 public HallTunneler tunnel(int min, int max, XorZRetriever currentAxisValue) {
   int cVal = currentAxisValue.get(current);
   if (nextDir != null) {
     Byte dir = getByteDirection(nextDir);
     Byte opDir = getByteDirection(nextDir.getOppositeFace());
     while (!(cVal >= min && cVal <= max)) {
       current = current.getFace(nextDir);
       current.setTypeId(0);
       current.getFace(BlockFace.UP).setTypeId(0);
       if (by < requester.getMinY()) {
         if (dir != null) {
           current.setTypeIdAndData(67, dir, false);
         }
         current = current.getFace(BlockFace.UP);
         current.getFace(BlockFace.UP).setTypeId(0);
       } else if (by > requester.getMinY()) {
         current = current.getFace(BlockFace.DOWN);
         current.setTypeId(0);
         if (by + BlockFace.DOWN.getModY() >= requester.getMinY()) {
           current.getFace(BlockFace.DOWN).setTypeIdAndData(67, opDir, false);
         }
         if (Material.AIR.equals(current.getFace(nextDir).getType())) {
           current = current.getFace(nextDir);
           while (Material.AIR.equals(current.getFace(BlockFace.DOWN).getType())) {
             current = current.getFace(BlockFace.DOWN);
             current.setTypeIdAndData(Material.LADDER.getId(), opDir, false);
           }
           break;
         }
       }
       cVal = currentAxisValue.get(current);
       by = current.getY();
     }
     nextDir = null;
   }
   return this;
 }