@Command(
      aliases = {"cylinder", "cyl", "c"},
      usage = "<block> [radius] [height]",
      flags = "h",
      desc = "Choose the cylinder brush",
      help = "Chooses the cylinder brush.\n" + "The -h flag creates hollow cylinders instead.",
      min = 1,
      max = 3)
  @CommandPermissions("worldedit.brush.cylinder")
  public void cylinderBrush(
      Player player,
      LocalSession session,
      EditSession editSession,
      Pattern fill,
      @Optional("2") double radius,
      @Optional("1") int height,
      @Switch('h') boolean hollow)
      throws WorldEditException {
    worldEdit.checkMaxBrushRadius(radius);
    worldEdit.checkMaxBrushRadius(height);

    BrushTool tool = session.getBrushTool(player.getItemInHand());
    tool.setFill(fill);
    tool.setSize(radius);

    if (hollow) {
      tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder");
    } else {
      tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder");
    }

    player.print(String.format("Cylinder brush shape equipped (%.0f by %d).", radius, height));
  }
  @Command(
      aliases = {"gravity", "grav"},
      usage = "[radius]",
      flags = "h",
      desc = "Gravity brush",
      help =
          "This brush simulates the affect of gravity.\n"
              + "The -h flag makes it affect blocks starting at the world's max y, "
              + "instead of the clicked block's y + radius.",
      min = 0,
      max = 1)
  @CommandPermissions("worldedit.brush.gravity")
  public void gravityBrush(
      Player player,
      LocalSession session,
      EditSession editSession,
      @Optional("5") double radius,
      @Switch('h') boolean fromMaxY)
      throws WorldEditException {
    worldEdit.checkMaxBrushRadius(radius);

    BrushTool tool = session.getBrushTool(player.getItemInHand());
    tool.setSize(radius);
    tool.setBrush(new GravityBrush(fromMaxY), "worldedit.brush.gravity");

    player.print(String.format("Gravity brush equipped (%.0f).", radius));
  }
  @Command(
      aliases = {"smooth"},
      usage = "[size] [iterations]",
      flags = "n",
      desc = "Choose the terrain softener brush",
      help =
          "Chooses the terrain softener brush.\n"
              + "The -n flag makes it only consider naturally occurring blocks.",
      min = 0,
      max = 2)
  @CommandPermissions("worldedit.brush.smooth")
  public void smoothBrush(
      Player player,
      LocalSession session,
      EditSession editSession,
      @Optional("2") double radius,
      @Optional("4") int iterations,
      @Switch('n') boolean naturalBlocksOnly)
      throws WorldEditException {

    worldEdit.checkMaxBrushRadius(radius);

    BrushTool tool = session.getBrushTool(player.getItemInHand());
    tool.setSize(radius);
    tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth");

    player.print(
        String.format(
            "Smooth brush equipped (%.0f x %dx, using "
                + (naturalBlocksOnly ? "natural blocks only" : "any block")
                + ").",
            radius,
            iterations));
  }
  @Command(
      aliases = {"clipboard", "copy"},
      usage = "",
      desc = "Choose the clipboard brush",
      help =
          "Chooses the clipboard brush.\n"
              + "The -a flag makes it not paste air.\n"
              + "Without the -p flag, the paste will appear centered at the target location. "
              + "With the flag, then the paste will appear relative to where you had "
              + "stood relative to the copied area when you copied it.")
  @CommandPermissions("worldedit.brush.clipboard")
  public void clipboardBrush(
      Player player,
      LocalSession session,
      EditSession editSession,
      @Switch('a') boolean ignoreAir,
      @Switch('p') boolean usingOrigin)
      throws WorldEditException {
    ClipboardHolder holder = session.getClipboard();
    Clipboard clipboard = holder.getClipboard();

    Vector size = clipboard.getDimensions();

    worldEdit.checkMaxBrushRadius(size.getBlockX());
    worldEdit.checkMaxBrushRadius(size.getBlockY());
    worldEdit.checkMaxBrushRadius(size.getBlockZ());

    BrushTool tool = session.getBrushTool(player.getItemInHand());
    tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard");

    player.print("Clipboard brush shape equipped.");
  }
  @Command(
      aliases = {"butcher", "kill"},
      usage = "[radius]",
      flags = "plangbtfr",
      desc = "Butcher brush",
      help =
          "Kills nearby mobs within the specified radius.\n"
              + "Flags:\n"
              + "  -p also kills pets.\n"
              + "  -n also kills NPCs.\n"
              + "  -g also kills Golems.\n"
              + "  -a also kills animals.\n"
              + "  -b also kills ambient mobs.\n"
              + "  -t also kills mobs with name tags.\n"
              + "  -f compounds all previous flags.\n"
              + "  -r also destroys armor stands.\n"
              + "  -l currently does nothing.",
      min = 0,
      max = 1)
  @CommandPermissions("worldedit.brush.butcher")
  public void butcherBrush(
      Player player, LocalSession session, EditSession editSession, CommandContext args)
      throws WorldEditException {
    LocalConfiguration config = worldEdit.getConfiguration();

    double radius = args.argsLength() > 0 ? args.getDouble(0) : 5;
    double maxRadius = config.maxBrushRadius;
    // hmmmm not horribly worried about this because -1 is still rather efficient,
    // the problem arises when butcherMaxRadius is some really high number but not infinite
    // - original idea taken from https://github.com/sk89q/worldedit/pull/198#issuecomment-6463108
    if (player.hasPermission("worldedit.butcher")) {
      maxRadius = Math.max(config.maxBrushRadius, config.butcherMaxRadius);
    }
    if (radius > maxRadius) {
      player.printError("Maximum allowed brush radius: " + maxRadius);
      return;
    }

    CreatureButcher flags = new CreatureButcher(player);
    flags.fromCommand(args);

    BrushTool tool = session.getBrushTool(player.getItemInHand());
    tool.setSize(radius);
    tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher");

    player.print(String.format("Butcher brush equipped (%.0f).", radius));
  }
  @Command(
      aliases = {"ex", "extinguish"},
      usage = "[radius]",
      desc = "Shortcut fire extinguisher brush",
      min = 0,
      max = 1)
  @CommandPermissions("worldedit.brush.ex")
  public void extinguishBrush(
      Player player, LocalSession session, EditSession editSession, @Optional("5") double radius)
      throws WorldEditException {
    worldEdit.checkMaxBrushRadius(radius);

    BrushTool tool = session.getBrushTool(player.getItemInHand());
    Pattern fill = new BlockPattern(new BaseBlock(0));
    tool.setFill(fill);
    tool.setSize(radius);
    tool.setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE)));
    tool.setBrush(new SphereBrush(), "worldedit.brush.ex");

    player.print(String.format("Extinguisher equipped (%.0f).", radius));
  }