@EventHandler
  public void openInventory(InventoryOpenEvent ioe) {
    if (!(ioe.getPlayer() instanceof Player)) {
      return;
    }

    Player player = (Player) ioe.getPlayer();
    Game game = Main.getInstance().getGameManager().getGameOfPlayer(player);

    if (game == null) {
      return;
    }

    if (game.getState() != GameState.RUNNING) {
      return;
    }

    if (ioe.getInventory().getType() == InventoryType.ENCHANTING
        || ioe.getInventory().getType() == InventoryType.BREWING
        || (ioe.getInventory().getType() == InventoryType.CRAFTING
            && !Main.getInstance().getBooleanConfig("allow-crafting", false))) {
      ioe.setCancelled(true);
      return;
    } else if (ioe.getInventory().getType() == InventoryType.CRAFTING
        && Main.getInstance().getBooleanConfig("allow-crafting", false)) {
      return;
    }

    if (game.isSpectator(player)) {
      if (ioe.getInventory().getName().equals(Main._l("ingame.spectator"))) {
        return;
      }

      ioe.setCancelled(true);
    }

    if (ioe.getInventory().getHolder() == null) {
      return;
    }

    if (game.getRegion().getInventories().contains(ioe.getInventory())) {
      return;
    }

    InventoryHolder holder = ioe.getInventory().getHolder();
    for (Class<?> interfaze : holder.getClass().getInterfaces()) {

      if (interfaze.equals(BlockState.class)) {
        game.getRegion().addInventory(ioe.getInventory());
        return;
      }

      for (Class<?> interfaze2 : interfaze.getInterfaces()) {
        if (interfaze2.equals(BlockState.class)) {
          game.getRegion().addInventory(ioe.getInventory());
          return;
        }
      }
    }
  }
  @EventHandler
  public void onPlayerInteract(PlayerInteractEvent pie) {
    Player player = pie.getPlayer();
    Game g = Main.getInstance().getGameManager().getGameOfPlayer(player);

    if (g == null) {
      if (pie.getAction() != Action.RIGHT_CLICK_BLOCK
          && pie.getAction() != Action.RIGHT_CLICK_AIR) {
        return;
      }

      Block clicked = pie.getClickedBlock();

      if (clicked == null) {
        return;
      }

      if (!(clicked.getState() instanceof Sign)) {
        return;
      }

      Game game = Main.getInstance().getGameManager().getGameBySignLocation(clicked.getLocation());
      if (game == null) {
        return;
      }

      if (game.playerJoins(player)) {
        player.sendMessage(ChatWriter.pluginMessage(ChatColor.GREEN + Main._l("success.joined")));
      }
      return;
    }

    if (g.getState() == GameState.STOPPED) {
      return;
    }

    Material interactingMaterial = pie.getMaterial();
    Block clickedBlock = pie.getClickedBlock();

    if (g.getState() == GameState.RUNNING) {
      if (pie.getAction() == Action.PHYSICAL) {
        if (clickedBlock != null
            && (clickedBlock.getType() == Material.WHEAT
                || clickedBlock.getType() == Material.SOIL)) {
          pie.setCancelled(true);
          return;
        }
      }

      if (pie.getAction() != Action.RIGHT_CLICK_BLOCK
          && pie.getAction() != Action.RIGHT_CLICK_AIR) {
        return;
      }

      if (clickedBlock != null) {
        if (clickedBlock.getType() == Material.LEVER
            && !g.isSpectator(player)
            && pie.getAction() == Action.RIGHT_CLICK_BLOCK) {
          if (!g.getRegion().isPlacedUnbreakableBlock(clickedBlock)) {
            g.getRegion().addPlacedUnbreakableBlock(clickedBlock, clickedBlock.getState());
          }
          return;
        }
      }

      if (g.isSpectator(player)) {
        if (interactingMaterial == Material.SLIME_BALL) {
          g.playerLeave(player, false);
          return;
        }

        if (interactingMaterial == Material.COMPASS) {
          g.openSpectatorCompass(player);
          pie.setCancelled(true);
          return;
        }
      }

      // Spectators want to block
      if (clickedBlock != null) {
        try {
          GameMode.valueOf("SPECTATOR");
        } catch (Exception ex) {
          for (Player p : g.getFreePlayers()) {
            if (!g.getRegion().isInRegion(p.getLocation())) {
              continue;
            }

            if (pie.getClickedBlock().getLocation().distance(p.getLocation()) < 2) {
              Location oldLocation = p.getLocation();
              if (oldLocation.getY() >= pie.getClickedBlock().getLocation().getY()) {
                oldLocation.setY(oldLocation.getY() + 2);
              } else {
                oldLocation.setY(oldLocation.getY() - 2);
              }

              p.teleport(oldLocation);
            }
          }
        }
      }

      if (clickedBlock != null) {
        if (clickedBlock.getType() == Material.ENDER_CHEST && !g.isSpectator(player)) {
          pie.setCancelled(true);

          Block chest = pie.getClickedBlock();
          Team chestTeam = g.getTeamOfEnderChest(chest);
          Team playerTeam = g.getPlayerTeam(player);

          if (chestTeam == null) {
            return;
          }

          if (chestTeam.equals(playerTeam)) {
            player.openInventory(chestTeam.getInventory());
          } else {
            player.sendMessage(
                ChatWriter.pluginMessage(ChatColor.RED + Main._l("ingame.noturteamchest")));
          }

          return;
        }
      }

      return;
    } else if (g.getState() == GameState.WAITING) {
      if (interactingMaterial == null) {
        pie.setCancelled(true);
        return;
      }

      if (pie.getAction() == Action.PHYSICAL) {
        if (clickedBlock != null
            && (clickedBlock.getType() == Material.WHEAT
                || clickedBlock.getType() == Material.SOIL)) {
          pie.setCancelled(true);
          return;
        }
      }

      if (pie.getAction() != Action.RIGHT_CLICK_BLOCK
          && pie.getAction() != Action.RIGHT_CLICK_AIR) {
        return;
      }

      switch (interactingMaterial) {
        case BED:
          pie.setCancelled(true);
          if (!g.isAutobalanceEnabled()) {
            g.getPlayerStorage(player).openTeamSelection(g);
          }

          break;
        case DIAMOND:
          pie.setCancelled(true);
          if (player.isOp() || player.hasPermission("bw.setup")) {
            g.start(player);
          } else if (player.hasPermission("bw.vip.forcestart")) {
            GameLobbyCountdownRule rule = Main.getInstance().getLobbyCountdownRule();
            if (rule.isRuleMet(g)) {
              g.start(player);
            } else {
              if (rule == GameLobbyCountdownRule.PLAYERS_IN_GAME
                  || rule == GameLobbyCountdownRule.ENOUGH_TEAMS_AND_PLAYERS) {
                player.sendMessage(
                    ChatWriter.pluginMessage(
                        ChatColor.RED + Main._l("lobby.notenoughplayers-rule0")));
              } else {
                player.sendMessage(
                    ChatWriter.pluginMessage(
                        ChatColor.RED + Main._l("lobby.notenoughplayers-rule1")));
              }
            }
          }
          break;
        case SLIME_BALL:
          pie.setCancelled(true);
          g.playerLeave(player, false);
          break;
        case LEATHER_CHESTPLATE:
          pie.setCancelled(true);
          player.updateInventory();
          break;
        default:
          break;
      }
    }
  }
  @EventHandler(priority = EventPriority.HIGHEST)
  public void onExplodeDestroy(EntityExplodeEvent eev) {
    if (eev.isCancelled()) {
      return;
    }

    if (eev.getEntity() == null) {
      return;
    }

    if (eev.getEntity().getWorld() == null) {
      return;
    }

    Game game =
        Main.getInstance().getGameManager().getGameByLocation(eev.getEntity().getLocation());

    if (game == null) {
      return;
    }

    if (game.getState() == GameState.STOPPED) {
      return;
    }

    Iterator<Block> explodeBlocks = eev.blockList().iterator();
    boolean tntDestroyEnabled =
        Main.getInstance().getBooleanConfig("explodes.destroy-worldblocks", false);
    boolean tntDestroyBeds = Main.getInstance().getBooleanConfig("explodes.destroy-beds", false);

    if (!Main.getInstance().getBooleanConfig("explodes.drop-blocks", false)) {
      eev.setYield(0F);
    }

    Material targetMaterial = game.getTargetMaterial();
    while (explodeBlocks.hasNext()) {
      Block exploding = explodeBlocks.next();
      if (!game.getRegion().isInRegion(exploding.getLocation())) {
        explodeBlocks.remove();
        continue;
      }

      if ((!tntDestroyEnabled && !tntDestroyBeds)
          || (!tntDestroyEnabled
              && tntDestroyBeds
              && exploding.getType() != Material.BED_BLOCK
              && exploding.getType() != Material.BED)) {
        if (!game.getRegion().isPlacedBlock(exploding)) {
          if (Main.getInstance().isBreakableType(exploding.getType())) {
            game.getRegion().addBreakedBlock(exploding);
            continue;
          }

          explodeBlocks.remove();
        } else {
          game.getRegion().removePlacedBlock(exploding);
        }

        continue;
      }

      if (game.getRegion().isPlacedBlock(exploding)) {
        game.getRegion().removePlacedBlock(exploding);
        continue;
      }

      if (exploding.getType().equals(targetMaterial)) {
        if (!tntDestroyBeds) {
          explodeBlocks.remove();
          continue;
        }

        // only destroyable by tnt
        if (!eev.getEntityType().equals(EntityType.PRIMED_TNT)
            && !eev.getEntityType().equals(EntityType.MINECART_TNT)) {
          explodeBlocks.remove();
          continue;
        }

        // when it wasn't player who ignited the tnt
        TNTPrimed primedTnt = (TNTPrimed) eev.getEntity();
        if (!(primedTnt.getSource() instanceof Player)) {
          explodeBlocks.remove();
          continue;
        }

        Player p = (Player) primedTnt.getSource();
        if (!game.handleDestroyTargetMaterial(p, exploding)) {
          explodeBlocks.remove();
          continue;
        }
      } else {
        game.getRegion().addBreakedBlock(exploding);
      }
    }
  }