事件总线与事件类
基本信息
| 属性 | 值 |
|---|---|
| 事件总线 | com.sk89q.worldedit.util.eventbus.EventBus(EventBus.java:56) |
| 总线获取 | WorldEdit.getInstance().getEventBus()(WorldEdit.java) |
| 注册方法 | EventBus.register(Object)(:139)、unregister(Object)(:149) |
| 事件基类 | event/Event.java:22(public abstract class Event) |
| 事件类总数 | 8 个具体事件 + 2 个接口/基类 + 2 个枚举 |
事件类清单
| 事件类 | 文件行 | 类型 | 说明 |
|---|---|---|---|
CommandEvent |
event/platform/CommandEvent.java:27 |
extends AbstractCancellable |
玩家执行命令时投递,可取消 |
CommandSuggestionEvent |
event/platform/CommandSuggestionEvent.java:30 |
extends Event |
客户端请求命令补全 |
ConfigurationLoadEvent |
event/platform/ConfigurationLoadEvent.java:27 |
extends Event |
配置加载完成,携带 LocalConfiguration |
EditSessionEvent |
event/extent/EditSessionEvent.java:65 |
extends Event |
编辑会话创建/关闭;WorldEdit.java:859-861 的 @deprecated 注释注明旧的 EditSessionFactories 已废弃、应改注册 EditSessionEvent |
PlatformReadyEvent |
event/platform/PlatformReadyEvent.java:25 |
extends Event |
平台就绪 |
PlatformInitializeEvent |
event/platform/PlatformInitializeEvent.java:29 |
extends Event |
平台初始化 |
BlockInteractEvent |
event/platform/BlockInteractEvent.java:29 |
implements Cancellable |
方块交互,可取消 |
PlayerInputEvent |
event/platform/PlayerInputEvent.java:28 |
implements Cancellable |
玩家输入,可取消 |
Cancellable |
event/Cancellable.java:23 |
interface | 可取消事件接口 |
AbstractCancellable |
event/AbstractCancellable.java:23 |
abstract class | Cancellable 的默认实现 |
InputType |
event/platform/InputType.java:22 |
enum | 输入类型 |
Interaction |
event/platform/Interaction.java:22 |
enum | 交互动作 |
分发机制
EventBus.post(Object event)(EventBus.java:165-185):
flattenHierarchy(event.getClass())展开事件的类型继承链(:169),因此父类事件的处理器也会收到子类事件- 按类型收集处理器,按优先级排序(
Collections.sort(dispatching),:180) - 逐个调用
dispatch(event, handler)(:183)
事件处理器异常处理
EventBus.dispatch 包裹每个处理器的调用(EventBus.java:194-200):
protected void dispatch(Object event, EventHandler handler) {
try {
handler.handleEvent(event);
} catch (InvocationTargetException e) {
logger.log(Level.SEVERE, "Could not dispatch event: " + event + " to handler " + handler, e);
}
}
EventHandler.handleEvent 会把处理器的任何 Throwable 包进 InvocationTargetException(EventHandler.java:72-78)。
结论:某个订阅者抛异常不会中断其它订阅者——异常被记为 SEVERE 日志后吞掉,分发循环继续。这与「静默失败」有本质区别(有日志、级别为最高),但玩家侧同样看不到提示。
本 mod 内部的投递点
| 事件 | 投递位置 | 触发源 |
|---|---|---|
PlatformReadyEvent |
ForgeWorldEdit.java:196-198 |
FMLServerStartedEvent |
ConfigurationLoadEvent |
WorldEditCommands.java:73-78 |
//we reload |
com.sk89q.worldedit.event.platform.CommandEvent |
ForgeWorldEdit.java:208-214 |
Forge CommandEvent(拦截全部服务端命令) |
CommandSuggestionEvent |
CommandWrapper.java:58-65 |
客户端 Tab 补全 |
注意
ForgeWorldEdit.onCommandEvent(:201-216)会对每个 MP 玩家执行的任意命令都投递 WorldEdit 的CommandEvent,并把event.parameters与命令名用空格拼接(Joiner.on(" ").join(split))。这是 mod 扩展拦截玩家命令的入口。
已废弃的空实现 API
WorldEdit.setEditSessionFactory(EditSessionFactory)(WorldEdit.java:863-876)被标注 @Deprecated,方法体只打一条 SEVERE 日志、不做任何事:
"…but EditSessionFactories have been removed in favor of extending EditSession's extents.
This may mean that any block logger / intercepters addons/plugins/mods that you have
installed will not intercept WorldEdit's changes! Please notify the maintainer…"
它是为旧版方块记录/拦截插件保留的兼容空壳:调用不报错,但拦截功能不会生效。这是死代码三档中的第 (b) 类变体——保留了签名却已无实现,调用方不会得到任何错误提示。1.7.10 版要拦截世界改动,正确做法是注册 EditSessionEvent(event/extent/EditSessionEvent.java:65)。
EditSessionFactories 作为类在本仓已不存在(find . -name 'EditSessionFactories.java' 无命中),全仓仅剩上述 2 处文字提及(WorldEdit.java:860 的 @deprecated javadoc 与 :873 的日志文本)。
订阅示例
SessionManager 用 @Subscribe 订阅 ConfigurationLoadEvent(SessionManager.java:282-287),并在收到时重建会话存储后端。