跳到主要内容

聊天事件

聊天事件在过去几年中经历了几次演变。 本指南将解释如何正确使用新的 AsyncChatEvent 及其 ChatRenderer。 AsyncChatEvent 是旧的 AsyncPlayerChatEvent 的改进版本, 它允许你为每个玩家单独渲染聊天消息。

AsyncChatEvent vs ChatEvent

AsyncChatEvent 和 ChatEvent 的主要区别在于 AsyncChatEvent 是异步触发的。

这意味着它不会阻塞主线程,并在监听器完成后发送聊天消息。 请注意,在异步上下文(即事件处理器)中使用 Bukkit API 是不安全的,可能会抛出异常。 如果你需要使用 Bukkit API,你可以使用 ChatEvent。 不过,我们建议使用 BukkitScheduler。

理解渲染器​

在我们开始使用新的聊天事件之前,我们需要理解新的渲染器是如何工作的。 渲染器是 Paper 允许插件在消息发送给玩家之前修改聊天消息的方式。 这是通过使用 ChatRenderer 接口及其 render 方法来实现的。之前,这是通过使用 AsyncPlayerChatEvent 的 setFormat 方法来完成的。

ChatRenderer#render
public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) {
// ...
}
  • render 方法在聊天消息发送给玩家时被调用。
  • source 参数是发送消息的玩家。
  • sourceDisplayName 参数是发送消息的玩家的显示名称。
  • message 参数是发送的消息。
  • viewer 参数是接收消息的玩家。
ChatRenderer.ViewerUnaware

如果你的渲染器不需要知道查看者的信息,你可以使用 ChatRenderer.ViewerUnaware 接口而不是 ChatRenderer 接口。 这将提高性能,因为消息只会被渲染一次,而不是为每个玩家单独渲染。

使用渲染器​

有两种使用渲染器的方式:

  1. 在一个类中实现 ChatRenderer 接口。
  2. 使用 lambda 表达式。

根据你的渲染器的复杂程度,你可能想使用其中一种方式。

实现 ChatRenderer 接口​

使用渲染器的第一种方式是在一个类中实现 ChatRenderer 接口。在这个例子中,我们将使用我们的 ChatListener 类。

接下来,我们需要通过使用 renderer 方法告诉事件使用渲染器。

ChatListener.java
public class ChatListener implements Listener, ChatRenderer { // 实现 ChatRenderer 和 Listener 接口

// 监听 AsyncChatEvent
@EventHandler
public void onChat(AsyncChatEvent event) {
event.renderer(this); // 告诉事件使用我们的渲染器
}

// 重写 render 方法
@Override
public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) {
// ...
}
}
备注

如果你决定为你的渲染器创建一个单独的类,重要的是要知道你不需要在每次调用事件时都实例化该类。 在这种情况下,你可以使用单例模式来创建该类的单个实例。

使用 lambda 表达式​

使用渲染器的另一种方式是使用 lambda 表达式。

ChatListener.java
public class ChatListener implements Listener {

@EventHandler
public void onChat(AsyncChatEvent event) {
event.renderer((source, sourceDisplayName, message, viewer) -> {
// ...
});
}
}

渲染消息​

现在我们有了渲染器,我们可以开始渲染消息了。

假设我们想要让我们的聊天看起来像这样:

要做到这一点,我们需要返回一个包含我们想要发送的消息的新 Component。

ChatListener.java
public class ChatListener implements Listener, ChatRenderer {

// 监听器逻辑

@Override
public Component render(Player source, Component sourceDisplayName, Component message, Audience viewer) {
return sourceDisplayName
.append(Component.text(": "))
.append(message);
}
}

现在你可以看到消息按照我们想要的方式渲染了。

总结​

这就是你需要了解的关于新的聊天事件及其渲染器的全部内容。 当然,你可以用组件做更多的事情。 如果你想了解更多关于组件的信息,你可以阅读 Component 文档。