Skip to main content

Introduction

note

This documentation page applies to both the Paper and Velocity projects.

Since Minecraft 1.7, the game has utilized components to represent text to be displayed by clients. Components offer a number of benefits over plain text strings which are enumerated below. Paper and Velocity natively implements the Adventure API to add component support wherever possible.

Why you should use Components

Previously, text was a linear structure with the only formatting options being confusing symbols like §c and §k to control basic colors and styles of text. Components are a tree-like structure which inherit style and colors from their parents.

Components have several types which do different things than just display raw text, like translating text to the client's language based on a key, or showing a client-specific keybind to a player.

All these component types support more style options like any RGB color, interaction events (click and hover). The other component types and these style options have poor or missing representations in the legacy string format.

Usage

Representing text as components is now the supported way of representing text for Paper and Velocity. They are used for almost all aspects of text being displayed to clients. Text like item names, lore, bossbars, team prefixes and suffixes, custom names, and much more all support components in respective APIs. Mojang has stated that client support for the legacy format with § will be removed in the future.

tip

In the Paper API, there are lots of deprecated methods and types that deal with this legacy format. This is to signal that a better alternative in components is available and should be migrated to going forward.

Creating Components

Components can be interacted with as objects. There are different interfaces for each type along with builders for all the types. These objects are immutable so when constructing more complex components, it's recommended to use builders to avoid creating new Component instances with every change.

// This is a sub-optimal construction of the
// component as each change creates a new component
final Component component = Component.text("Hello")
.color(TextColor.color(0x13f832))
.append(Component.text(" world!", NamedTextColor.GREEN));

/* This is an optimal use of the builder to create
the same component. Also note that Adventure
Components are designed for use with static method imports
to make code less verbose */
final Component component = text()
.content("Hello").color(color(0x13f832))
.append(text(" world!", GREEN))
.build();
In-Depth Documentation

For complete documentation on the Adventure Component API Paper and Velocity use, please look at the Adventure documentation.

MiniMessage

Paper and Velocity include the MiniMessage library which is a string representation of components. If you prefer working with strings rather than objects, MiniMessage is vastly superior to the legacy string format. It can utilize the tree structure for style inheritance and can represent the more complex component types while legacy cannot.

final Component component = MiniMessage.miniMessage().deserialize(
"<#438df2><b>This is the parent component; its style is " +
"applied to all children.\n<u><!b>This is the first child, " +
"which is rendered after the parent</!b></u><key:key.inventory></b></#438df2>"
);

We recommend using this format for user-facing input such as commands or configuration values.

In-Depth Documentation

MiniMessage is a part of Adventure, and you can find its documentation on Adventure's documentation.

tip

MiniMessage has a web viewer, which is useful for constructing more complicated components and seeing the results in real time.

JSON Format

Components can be serialized and deserialized from a standard JSON format. This format is used in Vanilla in various commands which accept component arguments like /tellraw. Below is a simple example of this format.

{
"text": "This is the parent component; its style is applied to all children.\n",
"color": "#438df2",
"bold": true,
"extra": [
{
"text": "This is this first child, which is rendered after the parent",
"underlined": true,
// This overrides the parent's "bold" value just for this component
"bold": false
},
{
// This is a keybind component which will display the client's keybind for that action
"keybind": "key.inventory"
}
]
}
In-Depth Documentation

The JSON format is fully documented on the Minecraft Wiki.

tip

There are online tools to make generating this format much easier like JSON Text Generator.

Serializers

Paper and Velocity come bundled with different serializers for converting between Components and other forms of serialized text.

GsonComponentSerializer

Converts between Component and JSON-formatted strings with convenience methods to directly deal with Gson's JsonElement. This conversion is lossless and is the preferred form of serialization for components that do not have to be edited by users regularly.

MiniMessage

Converts between Component and a MiniMessage-formatted string. This conversion is lossless and is the preferred form of serialization for components that have to be edited by users. There is also extensive customization you can add to the serializer, which is documented here.

PlainTextComponentSerializer

Serializes a Component into a plain text string. This is very lossy as all style information as well as most other types of components will lose information. There may be special handling for TranslatableComponents to be serialized into a default language, but generally this shouldn't be used except in certain circumstances, like logging to a text file.

LegacyComponentSerializer

caution

This is not recommended for use as the legacy format may be removed in the future.

Converts between Component and the legacy string format. This conversion is very lossy as component types and events do not have a legacy string representation.

A more useful use case is converting legacy text to MiniMessage format in a migration process.

final String legacyString = ChatColor.RED + "This is a legacy " + ChatColor.GOLD + "string";

// runs the legacy string through two serializers to convert legacy -> MiniMessage
final String miniMessageString = MiniMessage.miniMessage().serialize(
LegacyComponentSerializer.legacySection().deserialize(legacyString)
);
note

There are 2 built-in legacy serializers, one dealing with § symbols and the other for & symbols. They have their own instances available through LegacyComponentSerializer#legacySection() and LegacyComponentSerializer#legacyAmpersand().