未发布版本 v6.3.0-SNAPSHOT。 本页内容来自 alpha 分支,随时可能变更,不属于任何已发布版本。

commit 49619c6 · 注入于 2026-09-13 12:23 UTC

Skip to content

事件监听器

UltiTools 模块的事件监听与 Bukkit 的事件监听基本相同。

参见 Bukkit 事件监听器

创建监听器

创建一个实现 Listener 接口的类,并在处理事件的方法上添加 @EventHandler 注解。

java
@EventListener
public class BackListener implements Listener {

    @EventHandler
    public void onPlayerDeath(PlayerDeathEvent event) {
        ...
    }
}

@EventListener 注解有一个可选的 manualRegister 参数(默认为 false)。对于通过标准模块 JAR 路径加载的监听器(例如使用 @UltiToolsModule 的写法),设为 true 时组件扫描会跳过该监听器的自动注册,需要通过 getListenerManager().register(this, YourListener.class) 手动注册。

监听器注册

在继承了 UltiToolsPlugin 的类中的 registerSelf 中注册监听器。

六参数连接器构造器已标记为待移除

下面的示例调用的是六参数 UltiToolsPlugin 构造器,它带有 @Deprecated(since = "6.0.8", forRemoval = true) 并把资源目录路径写死,因此每次编译都会产生一条移除警告。 改用外部插件 API,在你自己的 JavaPlugin 里调用 UltiToolsAPI.connect,或者保留连接器、改调七参数构造器并自行传入 resourceFolderPath:这两种写法在 v6.2.5 上都可用。 连接器的替代签名仍在 issue #217 中讨论,移除动作本身跟踪于 issue #213

java
package com.ultikits.docs.listener;

import com.ultikits.ultitools.abstracts.UltiToolsPlugin;
import com.ultikits.ultitools.abstracts.data.AuditableDataEntity;
import com.ultikits.ultitools.abstracts.data.BaseDataEntity;
import com.ultikits.ultitools.annotations.*;
import com.ultikits.ultitools.interfaces.DataOperator;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.bukkit.entity.Player;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class UltiToolsConnector extends UltiToolsPlugin {

    public UltiToolsConnector(String pluginName, String version, List<String> authors, List<String> loadAfter, int minUltiToolsVersion, String mainClass) {
        super(pluginName, version, authors, loadAfter, minUltiToolsVersion, mainClass);
    }

    @Override
    public boolean registerSelf() throws IOException {
        // register listener
        getListenerManager().register(this, SomeListener.class);
        return true;
    }

    @Override
    public void unregisterSelf() {

    }

    @Override
    public void reloadSelf() {
        super.reloadSelf();
    }
}

当然,你也可以使用 UltiTools 提供的自动注册功能,详情可以查看这篇文章

临时事件监听

很多时候我们都只是需要临时监听事件,在传统的插件编写中,常常会维护一个列表来记录需要临时监听的玩家,这十分麻烦。

UltiTools 对 Bukkit 的事件监听器进行了封装,你可以十分便捷地在任何地方监听事件,即创即用,用后即销。

临时监听器构建器

从 v6.1.0 开始,使用现代的 TempListener 构建器 API 来创建更清洁、更灵活的临时监听器:

java
// 简单使用 - 监听所有方块交互事件
TempListener.common(PlayerInteractEvent.class)
    .listen(event -> {
        player.sendMessage("你点击了一个方块!");
        return true; // 返回 true 自动注销监听器
    });

构建器方法:

  • eventHandler(TempEventHandler<E> handler) — 设置事件处理器。返回 true 自动注销,返回 false 继续监听。
  • filter(Function<E, Boolean> filter) — 添加前置过滤器。返回 true 处理事件,返回 false 忽略事件。
  • priority(EventPriority priority) — 设置处理器优先级(默认:NORMAL)。
  • build() — 构建并返回 TempListener(需要手动 register())。
  • listen(TempEventHandler<E> handler) — 一步构建并立即注册。

build() 现在会传递你设置的过滤器

自 v6.3.0 起,.filter(x).build() 是同时获得「可过滤」与「可注销」监听器的推荐写法:build() 调用的是与 listen(...) 相同的四参构造器,因此你设置的过滤器会真正生效,对返回的 TempListener 调用 register() 就能拿到调用 unregister() 所需的句柄——一次构造,两种能力,不需要第二个监听器。 在 v6.3.0 之前,build() 调用的是没有 filter 参数的三参构造器,过滤器会被静默丢弃;listen(...) 虽然传递了过滤器,却返回 void,拿不到注销句柄。这两个缺口由同一处修复一并关闭。

示例:等待玩家与特定方块交互

java
// 仅监听左键点击木头类方块
TempListener.common(PlayerInteractEvent.class)
    .priority(EventPriority.HIGH)
    .filter(event -> {
        Block block = event.getClickedBlock();
        return block != null && block.getType().name().contains("WOOD");
    })
    .listen(event -> {
        event.getPlayer().sendMessage("你点击了木头方块!");
        return true; // 首次匹配后自动注销
    });

示例:等待玩家聊天回复(带超时)

java
// 监听玩家聊天
TempListener.common(AsyncPlayerChatEvent.class)
    .filter(event -> event.getPlayer().equals(targetPlayer))
    .listen(event -> {
        String message = event.getMessage();
        if (message.equalsIgnoreCase("yes")) {
            processConfirmation(targetPlayer);
        }
        return true; // 处理后自动注销
    });

INFO

TempEventHandler<E> 是一个函数式接口,接收事件并返回布尔值:

  • 返回 true 自动注销监听器。
  • 返回 false 保持监听器活跃,继续处理后续事件。

传统临时监听器(SimpleTempListener)

四个构造器已标记为在 Phase 7 移除

自 v6.3.0 起,SimpleTempListener 的无参构造器以及两个、三个参数的重载——包括下面示例用到的无过滤器 (Class, TempEventHandler) 形态——都带上了 @Deprecated(since = "6.3.0", forRemoval = true),计划在未来的 Phase 7 里程碑中移除。它们彼此容易混淆:两个三参数重载仅在最后一个参数是 EventPriority 还是过滤器 Function 上不同,编译期没有任何信号提醒选错了。推荐使用上方的构建器 API,或直接使用未被废弃的四参数全参构造器 new SimpleTempListener<>(eventClass, priority, handler, filter)

下面示例中传统的直接实例化写法仍然可用,但其构造器已进入移除计划;新代码请使用构建器:

java
// 传统方式 - 仍然可用,但其构造器已在 Phase 7 计划移除
TempListener listener = new SimpleTempListener(PlayerInteractEvent.class, event -> {
    // 做一些事...
    return true; // 返回 true 自动注销监听器
});
listener.register(); // 开始监听

对于特定玩家的事件,传统的 PlayerTempListener 也已弃用。改为使用构建器配合过滤器:

java
// 旧方式(已弃用):
// TempListener listener = new PlayerTempListener<>(
//     PlayerInteractEvent.class,
//     event -> { /* ... */ return true; },
//     targetPlayer
// );

// 新方式(推荐):
TempListener.common(PlayerInteractEvent.class)
    .filter(event -> event.getPlayer().equals(targetPlayer))
    .listen(event -> { /* ... */ return true; });

自 v6.3.0 起,本节顶部展示的 .filter(x).build() 就是同时获得「可过滤」与「可手动注销」监听器的推荐写法——不再需要直接构造 SimpleTempListener

贡献者

暂无相关贡献者

基于 MIT 许可发布