Chat Builder
Create rich, interactive chat messages with a clean fluent API — colors, formatting, clickable links, commands on click, hover text, and paginated lists.
Introduction
The Chat Builder module lets you compose rich chat messages in Minecraft without
wrestling with raw TextComponentString and Style objects.
Instead, you chain method calls in a single expression to describe exactly what each segment
of your message should look like and how it should behave.
The module is split into three focused classes:
- EriChat — the main fluent builder for rich messages
- ChatSegment — internal representation of a styled text fragment
- ChatPaginator — automatic pagination with navigation buttons
The Chat Builder runs on the server side and sends finished
ITextComponent objects to players via normal Minecraft chat packets.
No client-side code is required.
EriChat — Fluent builder
EriChat is the entry point for building chat messages. Call EriChat.create()
to start a new builder, chain any number of .text() segments with their styling, then
deliver the result with .to(player) or .broadcast().
Simple colored message
// Simple colored message
EriChat.create()
.text("[INFO] ").color(TextFormatting.GOLD).bold()
.text("Welcome to the server!").color(TextFormatting.WHITE)
.to(player);
Clickable links and commands
Each segment can carry a click action — either a chat command or a URL — and an optional hover tooltip shown when the player moves their cursor over the text.
// Clickable message
EriChat.create()
.text("[Teleport] ").color(TextFormatting.GREEN)
.command("/tp spawn").hover("Click to teleport")
.text("[Website] ").color(TextFormatting.AQUA)
.url("https://example.com").hover("Open website")
.to(player);
Broadcasting to all players
// Broadcast to all online players
EriChat.create()
.text("[Announcement] ").color(TextFormatting.RED).bold()
.text("Server restarting in 5 minutes.").color(TextFormatting.YELLOW)
.broadcast();
Method reference
Every call to .text() starts a new segment. Formatting methods called after
.text() apply only to that segment, not to previous ones.
| Method | Description |
|---|---|
create() |
Static factory — starts a new builder. |
text(String) |
Appends a new text segment and makes it current. |
color(TextFormatting) |
Sets the color of the current segment. |
bold() |
Applies bold formatting to the current segment. |
italic() |
Applies italic formatting to the current segment. |
underline() |
Underlines the current segment. |
strikethrough() |
Applies strikethrough to the current segment. |
obfuscated() |
Applies the obfuscated (random characters) effect. |
command(String) |
On click, runs the given command (e.g. "/tp spawn"). |
suggest(String) |
On click, suggests the text in the player's chat input. |
url(String) |
On click, opens the given URL in the browser. |
hover(String) |
Sets the tooltip shown when hovering over the current segment. |
build() |
Assembles and returns the final ITextComponent. |
to(EntityPlayerMP) |
Builds and sends the message to one player. |
to(EntityPlayerMP...) |
Builds and sends the message to multiple players. |
broadcast() |
Builds and sends the message to every online player. |
ChatSegment — Internal segment
Every call to .text() on an EriChat builder internally creates a
ChatSegment instance. A segment holds a single string together with all the style
information applied after the .text() call: color, bold, italic, underline,
strikethrough, obfuscated, click event, and hover event.
When .build() or a delivery method is invoked, each ChatSegment is
converted to a TextComponentString with a corresponding Style object,
then appended to a parent TextComponentString as a sibling.
ChatSegment is an internal class. You never instantiate it directly — the
EriChat builder manages it for you. It is documented here for contributors
and advanced users who wish to extend the framework.
Lifecycle of a segment
- You call
.text("some text")— a newChatSegmentis created and set as current. - You call style methods (
.color(),.bold(),.command(), etc.) — they mutate the current segment. - You call
.text()again — a new segment is created; the previous one is finalized. - You call
.build()— each segment is converted to aTextComponentStringwith aStyleand chained as siblings.
ChatPaginator — Pagination
ChatPaginator splits a list of lines into pages and sends them to a player with
automatic << Prev and Next >> navigation buttons.
Each navigation button generates a click command that re-runs your base command with the
appropriate page number.
ChatPaginator paginator = ChatPaginator.create("/mycommand page")
.title("Player List")
.linesPerPage(8)
.headerColor(TextFormatting.GOLD);
for (String name : playerNames) {
paginator.add(name);
}
paginator.send(player, 1); // show page 1
In the example above, if there are 20 players, the paginator creates 3 pages of 8, 8, and 4
lines respectively. The Next >> button on page 1 sends the click command
/mycommand page 2, and so on.
Navigation buttons
Navigation buttons are generated automatically by send():
- If there is a previous page:
<< Prevruns/mycommand page N-1 - If there is a next page:
Next >>runs/mycommand page N+1 - Both buttons show a hover tooltip indicating the target page number.
- Buttons are omitted when there is only one page.
Method reference
| Method | Description |
|---|---|
create(String commandBase) |
Static factory. commandBase is the command prefix used to build navigation click events (e.g. "/mycommand page"). |
title(String) |
Sets the header title displayed at the top of each page. |
linesPerPage(int) |
Number of content lines per page (default: 8). |
headerColor(TextFormatting) |
Color of the title and separator line. |
lineColor(TextFormatting) |
Color of regular content lines. |
navColor(TextFormatting) |
Color of the navigation buttons (<< Prev / Next >>). |
add(String) |
Appends a single line to the list. |
addAll(List<String>) |
Appends all lines from a list at once. |
getPageCount() |
Returns the total number of pages based on current lines and linesPerPage. |
send(EntityPlayerMP, int page) |
Sends the specified page to the player (1-indexed). Out-of-range pages are clamped silently. |
Complete Example
The following example shows how to send a rich RPG-style level-up message to a player. It combines colors, bold, underline, a click command, and a hover tooltip in a single fluent chain.
// Rich RPG message
EriChat.create()
.text("★ ").color(TextFormatting.GOLD)
.text("You reached ").color(TextFormatting.WHITE)
.text("Level 10").color(TextFormatting.GREEN).bold()
.text("! ").color(TextFormatting.WHITE)
.text("[Skills]").color(TextFormatting.AQUA).underline()
.command("/skills").hover("View your skills")
.to(player);
What the player sees in chat:
★ You reached Level 10 ! [Skills] (hover: "View your skills" | click: /skills)
Paginator + Command integration
A common pattern is to register a command that accepts a page argument and delegates
to ChatPaginator:
public class CommandPlayerList extends CommandBase {
@Override public String getName() { return "players"; }
@Override public String getUsage(ICommandSender s) { return "/players [page]"; }
@Override
public void execute(MinecraftServer server, ICommandSender sender, String[] args) {
EntityPlayerMP player = (EntityPlayerMP) sender;
int page = args.length > 1 ? Integer.parseInt(args[1]) : 1;
List<String> names = new ArrayList<>();
for (EntityPlayerMP p : server.getPlayerList().getPlayers()) {
names.add(p.getName());
}
ChatPaginator paginator = ChatPaginator.create("/players page")
.title("Online Players")
.linesPerPage(8)
.headerColor(TextFormatting.GOLD)
.lineColor(TextFormatting.WHITE)
.navColor(TextFormatting.YELLOW)
.addAll(names);
paginator.send(player, page);
}
}
All Chat Builder classes are in the fr.eri.eriapi.chat package:
import fr.eri.eriapi.chat.EriChat;import fr.eri.eriapi.chat.ChatPaginator;