Chat Events
The chat event has evolved a few times over the years.
This guide will explain how to properly use the new AsyncChatEvent
and its ChatRenderer
.
The AsyncChatEvent
is an improved version of the old AsyncPlayerChatEvent
that allows you to render chat messages individually for each player.
AsyncChatEvent
vs ChatEvent
The key difference between AsyncChatEvent
and ChatEvent
is that
AsyncChatEvent
is fired asynchronously.
This means that it does not block the main thread and sends the chat message when the listener has completed.
Be aware that using the Bukkit API in an asynchronous context (i.e. the event handler) is unsafe and exceptions may be thrown.
If you need to use the Bukkit API, you can use ChatEvent
.
However, we recommend using BukkitScheduler
.
Understanding the renderer
Before we can start using the new chat event, we need to understand how the new renderer works.
The renderer is Paper's way of allowing plugins to modify the chat message before it is sent to the player.
This is done by using the ChatRenderer
interface with its
render
method. Previously, this was done by using the AsyncPlayerChatEvent
with its setFormat
method.
public @NotNull Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer) {
// ...
}
- The
render
method is called when a chat message is sent to the player. - The
source
parameter is the player that sent the message. - The
sourceDisplayName
parameter is the display name of the player that sent the message. - The
message
parameter is the message that was sent. - The
viewer
parameter is the player that is receiving the message.
ChatRenderer.ViewerUnaware
If your renderer does not need to know about the viewer, you can use the
ChatRenderer.ViewerUnaware
interface instead of the ChatRenderer
interface.
This will benefit performance as the message will only be rendered once instead of each individual player.
Using the renderer
There are two ways to use the renderer.
- Implementing the
ChatRenderer
interface in a class. - Using a lambda expression.
Depending on the complexity of your renderer, you may want to use one or the other.
Implementing the ChatRenderer
interface
The first way of using the renderer is by implementing the ChatRenderer
interface in a class. In this example, we will be using our ChatListener
class.
Next, we need to tell the event to use the renderer by using the
renderer
method.
public class ChatListener implements Listener, ChatRenderer { // Implement the ChatRenderer and Listener interface
// Listen for the AsyncChatEvent
@EventHandler
public void onChat(AsyncChatEvent event) {
event.renderer(this); // Tell the event to use our renderer
}
// Override the render method
@Override
public @NotNull Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer) {
// ...
}
}
If you decide to create a separate class for your renderer, it is important to know that you don't need to instantiate the class every time the event is called. In this case, you can use the singleton pattern to create a single instance of the class.
Using a lambda expression
Another way of using the renderer is by using a lambda expression.
public class ChatListener implements Listener {
@EventHandler
public void onChat(AsyncChatEvent event) {
event.renderer((source, sourceDisplayName, message, viewer) -> {
// ...
});
}
}
Rendering the message
Now that we have our renderer, we can start rendering the message.
Let's say we want to render our chat to look like this:
To do this, we need to return a new Component
that contains the message we want to send.
public class ChatListener implements Listener, ChatRenderer {
// Listener logic
@Override
public @NotNull Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer) {
return sourceDisplayName
.append(Component.text(": "))
.append(message);
}
}
Now you can see that the message is rendered as we wanted it to be.
Conclusion
That is all you need to know about the new chat event and its renderer. Of course there are many more things you can do with components in general. If you want to learn more about components, you can read the Component Documentation.