@EventHandler
  public void onPlayerInteract(PlayerInteractEvent event) {
    if (!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
      return;
    }
    if (event.getClickedBlock() == null || event.getClickedBlock().getType() == Material.AIR) {
      return;
    }

    if (!context.isValidWorld(event.getPlayer().getWorld().getName())) return;

    SafeCityPlayer scPlayer = context.getPlayer(event.getPlayer());

    if (scPlayer.getCoolDownState()) {
      return;
    }
    if (scPlayer.getZoneManager().isResizing()) {
      return;
    }

    boolean hasTool = false;
    if (scPlayer.getBukkitPlayer().getItemInHand().getType() == SafeCityTool.ZoneTool.material()) {
      hasTool = true;
    }
    if (scPlayer.getBukkitPlayer().getItemInHand().getType()
        == SafeCityTool.ZoneTool3d.material()) {
      hasTool = true;
    }
    if (!hasTool) {
      return;
    }

    World blockWorld = event.getClickedBlock().getWorld();
    Location blockLocation = event.getClickedBlock().getLocation();
    ThinLocation blockThinLocation = context.toThinLocation(blockLocation);

    // does a zone already exist here?
    SafeCityZone zone = context.getZone(blockThinLocation, blockWorld);
    SafeCitySubZone subZone = context.getSubZone(blockThinLocation, blockWorld);

    // if clicked a corner, ignore (resizing)
    if (zone != null && zone.isCornerLocation(blockThinLocation, blockWorld, false)) {
      return;
    }
    if (subZone != null && subZone.isCornerLocation(blockThinLocation, blockWorld, true)) {
      return;
    }

    // check if player has permission
    if (!this.checkPermission(event, scPlayer, zone, subZone)) {
      return;
    }

    initCreation(event, scPlayer, zone);
  }
  private void createSubZone(
      SafeCityPlayer scPlayer, PlayerInteractEvent event, SafeCityZone zone) {
    // define second click
    scPlayer
        .getZoneManager()
        .setNewZoneLocation2(context.toThinLocation(event.getClickedBlock().getLocation()));

    // subzone-creation zone click mismatch
    SafeCityZone firstClickZone =
        context.getZone(
            scPlayer.getZoneManager().getNewZoneLocation1(), scPlayer.getBukkitPlayer().getWorld());
    SafeCityZone secondClickZone =
        context.getZone(
            scPlayer.getZoneManager().getNewZoneLocation2(), scPlayer.getBukkitPlayer().getWorld());

    if (firstClickZone != secondClickZone) {
      scPlayer.getZoneManager().clearCreationData();
      scPlayer.startCoolDown(2L);

      scPlayer.getBukkitPlayer().sendMessage(context.getMessageHandler().Zone_Mismatch());
      return;
    }

    ThinLocation[] clickedCorners =
        context.sortCorners(
            scPlayer.getZoneManager().getNewZoneLocation1(),
            scPlayer.getZoneManager().getNewZoneLocation2());

    // check if subzone is on the edge of the primary zone (lesser)
    if (clickedCorners[0].getBlockX() == zone.getLesserCorner().getBlockX()
        || clickedCorners[0].getBlockZ() == zone.getLesserCorner().getBlockZ()) {
      scPlayer
          .getBukkitPlayer()
          .sendMessage(ChatColor.RED + "Sub-zone cannot be on the edge of the primary zone.");
      return;
    }

    // check if subzone is on the edge of the primary zone (greater)
    if (clickedCorners[1].getBlockX() == zone.getGreaterCorner().getBlockX()
        || clickedCorners[1].getBlockZ() == zone.getGreaterCorner().getBlockZ()) {
      scPlayer
          .getBukkitPlayer()
          .sendMessage(ChatColor.RED + "Sub-zone cannot be on the edge of the primary zone.");
      return;
    }

    // 2D SubZone
    if (scPlayer.getBukkitPlayer().getItemInHand().getType() == SafeCityTool.ZoneTool.material()) {
      clickedCorners[0] =
          new ThinLocation(clickedCorners[0].getBlockX(), 1, clickedCorners[0].getBlockZ());
      clickedCorners[1] =
          new ThinLocation(
              clickedCorners[1].getBlockX(),
              (scPlayer.getBukkitPlayer().getWorld().getMaxHeight() - 1),
              clickedCorners[1].getBlockZ());
    }

    int width = Math.abs(clickedCorners[1].getBlockX() - clickedCorners[0].getBlockX()) + 1;
    int length = Math.abs(clickedCorners[1].getBlockZ() - clickedCorners[0].getBlockZ()) + 1;
    int height = Math.abs(clickedCorners[1].getBlockY() - clickedCorners[0].getBlockY()) + 1;

    if (scPlayer.getBukkitPlayer().getItemInHand().getType() == SafeCityTool.ZoneTool.material()) {
      if (width < 5 || length < 3) {
        scPlayer.getZoneManager().clearCreationData();
        scPlayer.startCoolDown(2L);

        scPlayer.getBukkitPlayer().sendMessage(context.getMessageHandler().SubZone_Too_Small());
        return;
      }
    }

    if (isOverlapping(scPlayer, clickedCorners[0], clickedCorners[1])) {
      scPlayer.getBukkitPlayer().sendMessage(context.getMessageHandler().Zone_Overlap());
      return;
    }

    if (scPlayer.getBukkitPlayer().getItemInHand().getType()
        == SafeCityTool.ZoneTool3d.material()) {
      if (width < 5 || length < 5 || height < 3) {
        scPlayer.getZoneManager().clearCreationData();
        scPlayer.startCoolDown(2L);

        scPlayer.getBukkitPlayer().sendMessage(context.getMessageHandler().SubZone3D_Too_Small());
        return;
      }
    }

    if (scPlayer.getBukkitPlayer().getItemInHand().getType()
        != SafeCityTool.ZoneTool3d.material()) {
      clickedCorners[0] =
          new ThinLocation(clickedCorners[0].getBlockX(), 1, clickedCorners[0].getBlockZ());
      clickedCorners[1] =
          new ThinLocation(
              clickedCorners[1].getBlockX(),
              (scPlayer.getBukkitPlayer().getWorld().getMaxHeight() - 1),
              clickedCorners[1].getBlockZ());
    }

    SafeCitySubZone newSubZone =
        new SafeCitySubZone(
            context,
            zone.getId(),
            zone.getFounder(),
            scPlayer.getBukkitPlayer().getWorld(),
            clickedCorners[0],
            clickedCorners[1]);

    context.addSubZone(newSubZone);

    scPlayer.getBukkitPlayer().sendMessage(context.getMessageHandler().Zone_Sub_Created());

    // update the children
    scPlayer.getZoneManager().setCurrentZone(zone);

    context
        .getConsole()
        .sendMessage(
            new StringBuilder()
                .append(ChatColor.GOLD)
                .append("Player ")
                .append(ChatColor.RED)
                .append(scPlayer.getBukkitPlayer().getName())
                .append(ChatColor.GOLD)
                .append(" created a new sub-zone. W:")
                .append(ChatColor.RED)
                .append(newSubZone.getWidth())
                .append(ChatColor.GOLD)
                .append(" L:")
                .append(ChatColor.RED)
                .append(newSubZone.getLength())
                .append(ChatColor.GOLD)
                .append(" H:")
                .append(ChatColor.RED)
                .append(newSubZone.getHeight())
                .toString());

    context.addNewSubZoneToMap(newSubZone);
  }