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):

  1. 用 READ_CLASSES(:30)去重 —— 同一 Class 只扫描一次。
  2. 遍历 c.getMethods(),挑出带 @MENetworkEventSubscribe 的方法(:40-41)。
  3. 强制两条约束,任一违反就抛 IllegalStateException:
    • 方法必须恰好 1 个参数(:66-67)
    • 参数类型必须是 MENetworkEvent 子类(:59-62)
  4. 索引结构是两层: 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 来保证这点。

相关条目