data-driven event system
1# Events
2
3Commander introduces a new data pack event system, which allows data packs to listen to events just like mods.
4
5The best practice is to have a generic Fabric event and register Commander as one of its listeners.
6
7## Creating event types
8
9To implement event support for your mod you must first register an event type for Commander to dispatch. You can build and register events with the `EventType.Builder` class.
10
11```java
12public static final EventType CUSTOM_EVENT = EventType.builder().build(new Identifier("modid", "custom_event"));
13```
14
15If your event requires a return type, you can specify a cancel term codec with `cancelTerm()`.
16
17```java
18EventType.builder()
19 .cancelTerm(Codec.INT)
20 .build(new Identifier("modid", "custom_event"));
21```
22
23Events can accept additional parameters using `extension()`. After specifying an extension you can return a custom type.
24
25```java
26EventType.builder()
27 .extension(Codec.STRING, subscriptions -> {
28 //handle data.
29 return /*Return listeners*/;
30 })
31 .build(new Identifier("modid", "custom_event"));
32```
33
34The default return type is `List<Command.Conditioned>`.
35
36## Invoking the event
37
38If you didn't specify an extension, or opted to return a `List<Command.Conditioned>`, you can use the included `EventExecutors` util.
39
40To use the util, you have to pass the event type, the execution world, and a loot context supplier.
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 /*Optional.empty() in 1.20.4*/);
51}
52```
53
54If you did specify an extension, or are using an unsupported return type, you'll have to write custom resolution logic.
55
56To do that you'll simply have to create an `EventContext`. `EventContext` is used to pass execution parameters to commands.
57
58```java
59EventContext context = EventContext.builder(type)
60 .addParameter(EventKey.LOOT_CONTEXT, /*instance of loot context*/)
61 .build();
62for (Command.Conditioned subscriber : subscribers) subscriber.execute(context);
63```
64To get the return value, you can call `getReturnValue(def)`, the default value can be null. The return type is generic.
65
66```java
67boolean val = context.getReturnValue(def);
68if (val != def) return val;
69```