data-driven event system
1# 事件
2
3本模组引入了全新的数据包事件系统,使数据包能够像模组一样监听事件。
4
5最好的实践办法就是找到一个 Fabric 的事件,让本模组对它进行监听。
6
7## 创建事件类型
8
9为了实现模组的事件支持,你需要先注册一个事件类型,以便本模组进行分发。你可以通过 `EventType.Builder` 类来构建并注册事件。
10
11```java
12public static final EventType CUSTOM_EVENT = EventType.builder().build(new Identifier("modid", "custom_event"));
13```
14
15如果你的事件需要返回类型,你可以通过 `cancelTerm()` 来指定取消条件编解码器。
16
17```java
18EventType.builder()
19 .cancelTerm(Codec.INT)
20 .build(new Identifier("modid", "custom_event"));
21```
22
23通过使用 `extension()`,事件可以接受额外的形式参数。在指定扩展后,你可以返回自定义类型。
24
25```java
26EventType.builder()
27 .extension(Codec.STRING, subscriptions -> {
28 //处理数据
29 return /*返回监听者*/;
30 })
31 .build(new Identifier("modid", "custom_event"));
32```
33
34默认的返回类型是 `List<Command.Conditioned>`。
35
36## 调用事件
37
38如果你没有指定扩展,或选择返回 `List<Command.Conditioned>`,你可以使用附带的 `EventExecutors` 辅助单元。
39
40为了使用这一辅助单元,你需要传递:事件类型、执行的世界,以及战利品的上下文提供者。
41
42```java
43CustomEvent.EVENT.register((world, entity) -> runVoid(CUSTOM_EVENT, world, () -> makeContext(world, entity, entity.getPos())));
44```
45
46```java
47private static LootContext makeContext(ServerWorld world, Entity entity, Vec3d origin) {
48 LootContextParameterSet.Builder builder = new LootContextParameterSet.Builder(world);
49 builder.add(THIS_ENTITY, entity).add(ORIGIN, origin);
50 return new LootContext.Builder(builder.build(LootContextTypes.COMMAND)).build(null /*在 1.20.4,.empty()可选*/);
51}
52```
53
54如果你指定了扩展,或者使用了不受支持的返回类型,就需要编写自定义的解析逻辑。
55
56为了编写这一逻辑,你需要创建 `EventContext`。`EventContext` 用于把执行形式参数传递给命令。
57
58```java
59EventContext context = EventContext.builder(type)
60 .addParameter(EventKey.LOOT_CONTEXT, /*战利品的上下文的实例*/)
61 .build();
62for (Command.Conditioned subscriber : subscribers) subscriber.execute(context);
63```
64你可以通过调用 `getReturnValue(def)` 来获取返回的值,默认值可以为空值。返回的类型是 generic。
65
66```java
67boolean val = context.getReturnValue(def);
68if (val != def) return val;
69```