Messages and text
Lesson 6.2
Chat messages, action-bar hints, command replies: mods talk to players a lot. The easy helpers send plain text. For colours, translations and texts built from parts, the API has text components.
Plain messages
You know these already:
player.send_message("Hello!"); // chat
player.send_message(std::format("You have {} rubies.", n)); // chat, with formatting
player.send_action_bar("Ready."); // above the hotbar
clight::broadcast("The event starts now!"); // chat, to everyone
They are all server-side. std::format builds a std::string the same way clight::log does: {} is replaced by the next value.
Text components
A text is what Minecraft really sends: a piece of text with a style, which can have more pieces attached. In C++ it is a clight::Text. Make one, style it, send it:
clight::Text t = clight::literal("Hello!");
player.send_message(t);
That is exactly what player.send_message("Hello!") does inside. clight::Text releases itself, like every owned class (see Handles and strings).
| Function or method | Does |
|---|---|
clight::literal("...") |
A text with exactly these characters. |
clight::text::translatable("key") |
A text looked up in the player’s language file. |
t.color(0xRRGGBB) |
Sets the colour. |
t.append(child) |
Attaches a child text after this one. |
t.to_plain() |
The text without styles, as an Expected<std::string>. |
And where texts go:
| Method | Shows it |
|---|---|
player.send_message(t) |
In the player’s chat. |
player.send_action_bar(t) |
Above the player’s hotbar. |
t.server_broadcast() |
In everybody’s chat. |
ctx.send_success(t) / ctx.send_failure(t) |
As a command reply (both also take a plain string). |
None of them take your text away: you can send the same clight::Text again, or change it and send it once more.
Colours
Colours are written 0xRRGGBB: red, green and blue, each from 00 to FF.
clight::Text t = clight::literal("Ruby found!");
t.color(0xE0115F); // ruby red
player.send_message(t);
A few vanilla chat colours: green 0x55FF55, yellow 0xFFFF55, red 0xFF5555, aqua 0x55FFFF, gold 0xFFAA00, grey 0xAAAAAA.
Texts from parts
append builds a message with several colours. The child inherits the parent’s style unless it sets its own:
void send_score(clight::Entity player, int score) {
clight::Text msg = clight::literal("Your score: ");
msg.color(0xAAAAAA);
clight::Text value = clight::literal(std::to_string(score));
value.color(0xFFAA00);
msg.append(value); // msg keeps its own reference to value
player.send_message(msg);
}
append takes its own reference to the child, so value can go out of scope without breaking msg. When the last owner is gone, the game frees the text.
Translations
Mods are played in many languages. Instead of writing English into your code, write a translation key, and put the texts into language files:
player.send_message(clight::text::translatable("my_mod.welcome"));
assets/my_mod/lang/en_us.json:
{
"my_mod.welcome": "Welcome to the server!"
}
assets/my_mod/lang/de_de.json:
{
"my_mod.welcome": "Willkommen auf dem Server!"
}
Each player sees the text in their own language, and falls back to English when their language is missing. The key is sent as it is, so players without your mod see my_mod.welcome. For messages from a server-side mod that players may not have, use literal text.
Values in translations
For “You have 3 rubies”, the language file marks the value with %s, and add_arg adds it:
{ "my_mod.rubies": "You have %s rubies." }
clight::Text t = clight::text::translatable("my_mod.rubies");
t.add_arg(clight::literal(std::to_string(3)));
player.send_message(t);
Several add_arg calls fill %s in order; a language may also write %2$s and %1$s.
Styles, clicks and hovers
clight::Text link = clight::literal("[Open the wiki]");
link.set_style(CL_STYLE_BOLD | CL_STYLE_UNDERLINED, true); // false switches a style off on purpose
link.click(CL_TEXT_CLICK_OPEN_URL, "https://example.com/ruby-wiki");
link.hover(clight::literal("Opens the wiki in your browser"));
player.send_message(link);
The styles are CL_STYLE_BOLD, CL_STYLE_ITALIC, CL_STYLE_UNDERLINED, CL_STYLE_STRIKETHROUGH and CL_STYLE_OBFUSCATED. The click actions:
| Action | A click |
|---|---|
CL_TEXT_CLICK_OPEN_URL |
asks, then opens the address (https:// or http:// only) |
CL_TEXT_CLICK_RUN_COMMAND |
runs the command as the player ("/spawn") |
CL_TEXT_CLICK_SUGGEST_COMMAND |
puts the text into the chat box |
CL_TEXT_CLICK_COPY_TO_CLIPBOARD |
copies the value |
Titles
player.send_title("Round 2", "Get ready!"); // vanilla's times
player.send_title("Go!", {}, 5, 20, 10); // fade in, stay, fade out in ticks
player.clear_title();
An empty subtitle keeps the current one, and -1 keeps a time.
Messages only this player sees
On the client, clight::text::client_show_message(text, overlay) shows a chat line (overlay = true: above the hotbar) without sending anything to the server, and clight::text::client_show_title(...) a title. They work on any server, even one without your mod.
Reading a text
to_plain() turns a text back into a string, without colours:
if (auto plain = msg.to_plain()) clight::log::info("sent: {}", *plain);
Try it
Write void announce(std::string_view who, std::string_view what) that sends everyone a message like Alex found a diamond!, where the name is gold, the thing is aqua and the rest is white.
Show a solution
void add_part(clight::Text& parent, std::string_view s, cl_color color) {
clight::Text part = clight::literal(s);
part.color(color);
parent.append(part);
}
void announce(std::string_view who, std::string_view what) {
clight::Text msg = clight::literal("");
msg.color(0xFFFFFF);
add_part(msg, who, 0xFFAA00);
add_part(msg, " found ", 0xFFFFFF);
add_part(msg, what, 0x55FFFF);
add_part(msg, "!", 0xFFFFFF);
msg.server_broadcast();
}
The parent is an empty text that only holds the parts. add_part takes the parent by reference (clight::Text&), so it adds to the real message instead of a copy. Each part is released at the end of add_part, while msg keeps its own reference to it.
Recap: the easy helpers send plain strings (build them with + or std::format); clight::literal and clight::text::translatable make a clight::Text you colour with color, combine with append, and send with send_message or server_broadcast, and it releases itself.