Chat arguments

The CommandAPI provides three main classes to interact with chat formatting in Minecraft.

Chat color argument

The ChatColorArgument class is used to represent a given chat color (e.g. red or green)

Example - Username color changing plugin

Say we want to create a plugin to change the color of a player's username. We want to create a command of the following form:

/namecolor <chatcolor>

We then use the ChatColorArgument to change the player's name color:

LinkedHashMap<String, Argument> arguments = new LinkedHashMap<>();
arguments.put("chatcolor", new ChatColorArgument());

new CommandAPICommand("namecolor")
    .withArguments(arguments)
    .executesPlayer((player, args) -> {
        ChatColor color = (ChatColor) args[0];
	    player.setDisplayName(color + player.getName());
    })
    .register();

Spigot-based chat arguments

Developer's Note:

The two following classes, ChatComponentArgument and ChatArgument depend on a Spigot based server. This means that these arguments will not work on a non-Spigot based server, such as CraftBukkit. If you use this class on a non-Spigot based server, it will throw a SpigotNotFoundException

Spigot based servers include, but are not limited to:

Chat component argument

The ChatComponentArgument class accepts raw chat-based JSON as valid input. Despite being regular JSON, it must conform to the standard declared here, which consists of JSON that has a limited subset of specific keys (In other words, you can have a JSON object that has the key text, but not one that has the key blah).

This is converted into Spigot's BaseComponent[], which can be used for the following:

  • Broadcasting messages to all players on the server using:

    Bukkit.getServer().spigot().broadcast(BaseComponent[]);
    
  • Adding and setting pages to books using BookMeta:

    BookMeta meta = // ...
    meta.spigot().setPages(BaseComponent[]);
    
  • Sending messages to Player objects:

    Player player = // ...
    player.spigot().sendMessage(BaseComponent[]);
    
  • Sending messages to CommandSender objects:

    CommandSender sender = // ...
    sender.spigot().sendMessage(BaseComponent[]);
    

Example - Book made from raw JSON

Say we want to generate a book using raw JSON. For this example, we'll use the following JSON (generated from minecraftjson.com) to generate our book:

["", {
    "text": "Once upon a time, there was a guy call "
}, {
    "text": "Skepter",
    "color": "light_purple",
    "hoverEvent": {
        "action": "show_entity",
        "value": "Skepter"
    }
}, {
    "text": " and he created the "
}, {
    "text": "CommandAPI",
    "underlined": true,
    "clickEvent": {
        "action": "open_url",
        "value": "https://github.com/JorelAli/1.13-Command-API"
    }
}]

Since we're writing a book, we must ensure that all quotes have been escaped. This can also be performed on the minecraftjson.com website by selecting "book":

["[\"\",{\"text\":\"Once upon a time, there was a guy call \"},{\"text\":\"Skepter\",\"color\":\"light_purple\",\"hoverEvent\":{\"action\":\"show_entity\",\"value\":\"Skepter\"}},{\"text\":\" and he created the \"},{\"text\":\"CommandAPI\",\"underlined\":true,\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://github.com/JorelAli/1.13-Command-API\"}}]"]

Now let's define our command. Since book text is typically very large - too large to be entered into a chat, we'll make a command block compatible command by providing a player parameter:

/makebook <player> <contents>

Now we can create our book command. We use the player as the main target by using their name for the author field, as well as their inventory to place the book. We finally construct our book using the .setPages(BaseComponent[]) method:

LinkedHashMap<String, Argument> arguments = new LinkedHashMap<>();
arguments.put("player", new PlayerArgument());
arguments.put("contents", new ChatComponentArgument());

new CommandAPICommand("makebook")
    .withArguments(arguments)
    .executes((sender, args) -> {
        Player player = (Player) args[0];
        BaseComponent[] arr = (BaseComponent[]) args[1];
        
        //Create book
        ItemStack is = new ItemStack(Material.WRITTEN_BOOK);
        BookMeta meta = (BookMeta) is.getItemMeta(); 
        meta.setTitle("Custom Book");
        meta.setAuthor(player.getName());
        meta.spigot().setPages(arr);
        is.setItemMeta(meta);
        
        //Give player the book
        player.getInventory().addItem(is);
    })
    .register();

Chat argument

Developer's Note:

As of the time of writing (25th June 2020), it has been observed that the ChatArgument does not work on Spigot 1.16.1. This is not the case however for Spigot versions 1.15.2 and below.

Note:

The ChatArgument class is an argument similar to the GreedyStringArgument, in the sense that it has no terminator and must be defined at the end of your LinkedHashMap of arguments. For more information on this, please read the section on Greedy arguments.

The ChatArgument is basically identical to the GreedyStringArgument, with the added functionality of enabling entity selectors, such as @e, @p and so on. The ChatArgument also returns a BaseComponent[], similar to the ChatComponentArgument.

Example - Sending personalized messages to players

Say we wanted to broadcast a "personalized" message to players on the server. By "personalized", we mean a command which changes its output depending on who we are sending the output to. Simply put, we want a command of the following structure:

/pbroadcast <message>

Say we're on a server with 2 players: Bob and Michael. If I were to use the following command:

/pbroadcast Hello @p

Bob would receive the message "Hello Bob", whereas Michael would receive the message "Hello Michael". We can use the ChatArgument to create this "personalized" broadcast:

LinkedHashMap<String, Argument> arguments = new LinkedHashMap<>();
arguments.put("message", new ChatArgument());

new CommandAPICommand("pbroadcast")
    .withArguments(arguments)
    .executes((sender, args) -> {
        BaseComponent[] message = (BaseComponent[]) args[0];
    
        //Broadcast the message to everyone on the server
        Bukkit.getServer().spigot().broadcast(message);
    })
    .register();