@EventHandler(priority = EventPriority.NORMAL)
  public void onPlayerInteract(PlayerInteractEvent event) {
    if (event.isCancelled()) return;

    if (event.getAction() == org.bukkit.event.block.Action.LEFT_CLICK_BLOCK
        || event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK) {
      PlayerEvent playerEvent;
      if (SignUtil.isSign(event.getClickedBlock())) {
        playerEvent =
            new PlayerEvent(
                SignUtil.getSign(event.getClickedBlock()),
                event.getAction() == Action.LEFT_CLICK_BLOCK
                    ? PlayerEvent.Action.LEFT_CLICK
                    : PlayerEvent.Action.RIGHT_CLICK,
                event.getPlayer(),
                event);
      } else {
        playerEvent =
            new PlayerEvent(
                event.getClickedBlock(),
                event.getAction() == Action.LEFT_CLICK_BLOCK
                    ? PlayerEvent.Action.LEFT_CLICK
                    : PlayerEvent.Action.RIGHT_CLICK,
                event.getPlayer(),
                event);
      }
      mechanicsHandler.callPlayerEvent(playerEvent);
    }
  }
  public BMListener(BetterMechanics plugin) {
    mechanicsHandler = plugin.getMechanicsHandler();

    for (SignMechanicListener listener : mechanicsHandler.getSignMechanics()) {
      for (String identifier : listener.getIdentifiers()) {
        idMap.put(identifier.toLowerCase(), new Pair<String>(identifier, listener.getName()));
      }
    }
  }
 @EventHandler(priority = EventPriority.NORMAL)
 public void onBlockRedstoneChange(BlockRedstoneEvent event) {
   if (event.getNewCurrent() == event.getOldCurrent()
       || event.getNewCurrent() > 0 && event.getOldCurrent() > 0) return;
   RedstoneEvent redstoneEvent =
       new RedstoneEvent(
           (event.getNewCurrent() > 0) ? RedstoneEvent.State.ON : RedstoneEvent.State.OFF, event);
   for (BlockFace blockFace : blockFaces) {
     Block block = event.getBlock().getRelative(blockFace);
     redstoneEvent.setData(
         SignUtil.isSign(event.getBlock().getRelative(blockFace))
             ? Event.Type.SIGN
             : Event.Type.BLOCK,
         event.getBlock(),
         blockFace.getOppositeFace());
     mechanicsHandler.callRedstoneEvent(redstoneEvent);
   }
 }
 @EventHandler(priority = EventPriority.NORMAL)
 public void onBlockBreak(BlockBreakEvent event) {
   if (event.isCancelled()) return;
   PlayerEvent playerEvent;
   if (SignUtil.isSign(event.getBlock())) {
     playerEvent =
         new PlayerEvent(
             SignUtil.getSign(event.getBlock()),
             PlayerEvent.Action.BREAK,
             event.getPlayer(),
             event);
   } else {
     playerEvent =
         new PlayerEvent(event.getBlock(), PlayerEvent.Action.BREAK, event.getPlayer(), event);
   }
   mechanicsHandler.callPlayerEvent(playerEvent);
   event.setCancelled(playerEvent.isCancelled());
 }