Event(事件总线)

基本信息

属性 值
目录 com.gtnewhorizons.angelica.event
文件数 5
总行数 105
总线实现 Forge net.minecraftforge.eventbus.api.bus.EventBus(1.7.10 的新 eventbus API)
事件类 4 个(ClientEventType 是枚举不是事件)

它解决什么问题

Angelica 的渲染管线大量替换了原版 Minecraft / EntityRenderer 的内部流程。用 mixin 硬改会让下游 mod 无从插手,因此 Angelica 提供自己的事件总线,让 mod 能在关键渲染节点插入逻辑。

5 个文件全清单

# 文件 行数 类型 事件类?
1 ClientEvent.java 36 class extends MutableEvent ✅
2 ClientEventType.java 8 enum(4 项) ❌ 类型枚举
3 RenderChunkEvent.java 15 class implements RecordEvent ✅
4 RenderHandEvent.java 25 record implements RecordEvent, Cancellable ✅
5 ChunkBiomeDataChangedEvent.java 21 final class extends MutableEvent ✅

3 条独立总线

总线 宿主类 类型 行
ClientEvent.BUS ClientEvent EventBus<ClientEvent> ClientEvent.java:6
RenderChunkEvent.BUS RenderChunkEvent EventBus<RenderChunkEvent> RenderChunkEvent.java:6
RenderHandEvent.BUS RenderHandEvent CancellableEventBus RenderHandEvent.java:9
ChunkBiomeDataChangedEvent.BUS 自身 EventBus<...> ChunkBiomeDataChangedEvent.java:6

每个事件类自带 BUS 静态字段,用 EventBus.create(X.class) 创建 —— 没有全局 EventBus 容器,4 条总线完全独立。

逐事件表

ClientEvent(36 行)

成员 行 说明
event :8 public final ClientEventType
renderer :9 public final EntityRenderer(单参构造时为 null)
partialTicks :10 public final float(单参构造时为 0)
私有构造 (event) :12-16 置 renderer = null、partialTicks = 0
私有构造 (event, renderer, partialTicks) :18-22 完整构造
post(event, renderer, partialTicks) :24-27 每次 new 一个实例
post(event) :29-32 每次 new 一个实例

ClientEventType 4 项(ClientEventType.java:4-7):PRE_RENDER_GUI、PRE_RENDER_HUD、POST_RENDER_HUD、ON_TICK。

投递点全部在 HUDCaching(HUDCaching):

事件 位置
PRE_RENDER_GUI HUDCaching.java:75
PRE_RENDER_HUD HUDCaching.java:76
POST_RENDER_HUD HUDCaching.java:90、:187
ON_TICK 无投递点

已知问题:ON_TICK 枚举项存在但仓库内没有任何 post(ClientEventType.ON_TICK) 调用。它是被 mixin 投递还是纯预留,无法从本仓库判断(mixin 源集已确认无该调用)。

RenderChunkEvent(15 行)

无字段、无载荷,无参 record 式事件。post()(:10-13)投递 INSTANCE 单例(:8)。

投递点:src/mixin/java/.../mixins/early/celeritas/terrain/MixinRenderGlobal.java:182 RenderChunkEvent.post();

RenderHandEvent(25 行)

public record RenderHandEvent() —— 零组分的 record。

成员 行 说明
BUS :9 CancellableEventBus
INSTANCE :11 单例
post() :17-20 return BUS.post(INSTANCE),返回是否被取消

类 Javadoc(:4-6)明确:

Posted from net.coderbot.iris.pipeline.HandRenderer’s canRender Cancel the event to prevent the hand from rendering.

投递点在 vendored Iris 代码里:src/main/java/net/coderbot/iris/pipeline/HandRenderer.java:86 !RenderHandEvent.post()。net.coderbot 是 Iris 的包,这段不是 Angelica 自己的代码(见 Iris(内嵌))。即 Angelica 的事件总线依赖对内嵌 Iris 的一处修改才能工作。

ChunkBiomeDataChangedEvent(21 行)

成员 行 说明
BUS :6 EventBus
INSTANCE :8 可变单例
chunkX / chunkZ :10-11 public int(非 final)
post(chunkX, chunkZ) :13-19 写 INSTANCE 字段后投递

唯一已知问题(真实缺陷):INSTANCE 是带可变字段的单例,post 直接改写 INSTANCE.chunkX/chunkZ 再投递。若某个监听器在回调中再次触发 post(重入),外层遍历看到的 chunkX/chunkZ 会被内层覆盖,且当前正在处理的事件载荷已被销毁。对比 RenderChunkEvent/RenderHandEvent 的单例是不可变的(无字段),ClientEvent 则是每次 new(安全但有分配)—— 仓库内三种模式并存,只有 ChunkBiomeDataChangedEvent 采用了危险的那一种。

投递点:仓库内没有 post 调用,只有一个监听器注册 —— CeleritasSetup.java:12 ChunkBiomeDataChangedEvent.BUS.addListener(CeleritasSetup::onChunkBiomeDataChanged)。即只有监听方,没有投递方(投递应在 mixin 或 Celeritas 内部,按本仓库可见范围未找到)。

全部事件的统一防御模式

4 个 post 方法无一例外都以 if (!BUS.hasListeners()) return; 开头(ClientEvent.java:25、:30;RenderChunkEvent.java:11;RenderHandEvent.java:18;ChunkBiomeDataChangedEvent.java:14)。无监听器时零分配、零投递。

已知问题汇总

  1. ChunkBiomeDataChangedEvent 的可变单例(见上)—— 唯一有实质风险的实现。
  2. ON_TICK 无投递点(见上)—— 死枚举项或 mixin 投递,本仓库不可判定。
  3. 三种事件实例策略并存(每次 new / 不可变单例 / 可变单例),无统一约定。
  4. ClientEvent 字段 renderer 可为 null(:14):post(event) 单参重载时置 null。监听器若不判空直接用会 NPE。无 Javadoc 说明该字段可空。
  5. RenderHandEvent 的耦合方向倒置:Angelica 自己的事件总线,其投递点在内嵌的 Iris 源码里。Iris 若移除该调用,事件静默失效。
  6. 无任何 addListener 注册路径的文档:mod 如何订阅这些事件,仓库内没有 README 或示例。

相关条目

  • HUDCaching - ClientEvent 的唯一投递方
  • Iris(内嵌) - RenderHandEvent 投递点所在的上游代码
  • API 层 - 与本子系统平行的对外 API 面
  • CompatHandlers - HUDCaching 早退补丁的另一条通路
  • Proxy - ClientEvent 初始化时序的参照