NetworkEventBus(appeng.me.NetworkEventBus)
基本信息
| 属性 | 值 |
|---|---|
| 源码 | appeng/me/NetworkEventBus.java |
| 类声明行号 | 28 |
| 接口 | 无(Grid 私有持有,Grid.java:44) |
| 注解契约 | appeng.api.networking.events.MENetworkEventSubscribe |
职责
反射式的网络事件总线。AE2 的网格子系统之间不直接互相引用,全靠这个总线解耦。
订阅者注册
readClass(Class listAs, Class c)(NetworkEventBus.java:33-73):
- 用
READ_CLASSES(:30)去重 —— 同一 Class 只扫描一次。 - 遍历
c.getMethods(),挑出带@MENetworkEventSubscribe的方法(:40-41)。 - 强制两条约束,任一违反就抛
IllegalStateException:- 方法必须恰好 1 个参数(
:66-67) - 参数类型必须是
MENetworkEvent子类(:59-62)
- 方法必须恰好 1 个参数(
- 索引结构是两层:
EVENTS : Map<Class<? extends MENetworkEvent>, Map<Class, MENetworkEventInfo>>(:31)—— 外层是事件类型,内层的 key 是listAs(按宿主类型区分订阅者)。
注册调用点
readClass 只有两个调用方,都很关键:
| 调用方 | 行号 | 注册了什么 |
|---|---|---|
Grid 构造器 |
Grid.java:66 |
每个 IGridCache 实例(按实现类 valueClass 注册) |
Grid.add() |
Grid.java:133 |
每种新出现的 IGridHost 子类(此时还没有实例,只能按 mClass 注册) |
⚠️ 因为 Grid.add() 的注册条件是 nodes == null(Grid.java:129-134),
同一个宿主类只在本网第一次出现时才 readClass 一次。
派发
postEvent(Grid, MENetworkEvent)(NetworkEventBus.java:75)。
NetworkEventBus.java:123 有个 private static class NetworkEventDone extends Throwable
—— 用异常做栈展开信号来实现「打断上层传播」,这也是 NetworkEventBus 唯一一个
内部类;另两个内部类 EventMethod(:128)与 MENetworkEventInfo(:157)是索引结构。
与 Grid.postEvent 的联动
Grid.postEvent(Grid.java:194-199)在派发前后各夹一次
CraftingGridCache.pauseRebuilds() / unpauseRebuilds()。也就是说
任何网格事件的处理期间,自动装配(pattern rebuild)都是被冻结的。
// Grid.java:195-197
CraftingGridCache.pauseRebuilds();
final MENetworkEvent ret = this.eventBus.postEvent(this, ev);
CraftingGridCache.unpauseRebuilds();
postEventTo(IGridNode, MENetworkEvent)(Grid.java:202-204)是定向派发,
注意它没有夹 pause/unpause。
注意
- 事件总线是静态的:
EVENTS与READ_CLASSES都是static(NetworkEventBus.java:30-31)。readClass的去重因此是跨所有网络的。 - 因为
READ_CLASSES全局去重,同一个 cache 实现类在两张不同的网里 只有一份方法索引;Grid.java:64正是传value.getClass()而不是key来保证这点。