跳到主要内容

聊天事件

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

AsyncChatEvent vs ChatEvent

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

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

理解渲染器

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

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 文档