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’scanRenderCancel 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)。无监听器时零分配、零投递。
已知问题汇总
ChunkBiomeDataChangedEvent的可变单例(见上)—— 唯一有实质风险的实现。ON_TICK无投递点(见上)—— 死枚举项或 mixin 投递,本仓库不可判定。- 三种事件实例策略并存(每次 new / 不可变单例 / 可变单例),无统一约定。
ClientEvent字段renderer可为null(:14):post(event)单参重载时置 null。监听器若不判空直接用会 NPE。无 Javadoc 说明该字段可空。RenderHandEvent的耦合方向倒置:Angelica 自己的事件总线,其投递点在内嵌的 Iris 源码里。Iris 若移除该调用,事件静默失效。- 无任何
addListener注册路径的文档:mod 如何订阅这些事件,仓库内没有 README 或示例。
相关条目
- HUDCaching -
ClientEvent的唯一投递方 - Iris(内嵌) -
RenderHandEvent投递点所在的上游代码 - API 层 - 与本子系统平行的对外 API 面
- CompatHandlers - HUDCaching 早退补丁的另一条通路
- Proxy -
ClientEvent初始化时序的参照