-
Notifications
You must be signed in to change notification settings - Fork 2
Invokers
Similar to Fabric Callbacks, NanoEvents combines all the listeners into a single function that u can then invoke. NanoEvents are statically declared, and as such, all Invokers/Listeners must be static.
As an example, we will make an event that passes an integer to a function, and the listener can do some mathematical operation on it.
@Invoker("modid:event") // this is the id of the event you specified in your EVT file
public static int sumEvent(int i) {
}This is an example event, where you want custom handling of return types. So, to create an invoker, we need to give NanoEvents a pattern that we can repeat for every listener for our event. NanoEvents has 2 functions for this purpose, Logic#start and Logic#end, the bytecode enclosed by start and end is copy pasted over and over again, one time for each listener, each shallow recursive call is replaced with a call to a listener. A shallow recursive call is when you directly call the invoker method, from inside the invoker method and not another function. (This does mean no lambda support as of now)
So let's write our sum event
@Invoker("modid:event")
public static int sumEvent(int i) {
Logic.start();
i += sumEvent(i); // Now, for every listener to sumEvent, this line of code will be copy and pasted, but the call to sumEvent is replaced with a call to the listener
Logic.end();
return i;
}Good IDEs, like intellij, will warn you about recursive calls and other nonsense, just ignore them.
The transformed function will look like this
@Invoker("modid:event")
public static int sumEvent(int i) {
i += sumListener(i);
i += mySumListener(i);
i += hisSumListener(i);
return i;
}NanoEvents will handle all the transformations from here, in your code, you can directly invoke sumEvent and at runtime, NanoEvents will transform it for you.
You may have noticed that when there is only one listener for the sumEvent, that the resulting code has extra operations and could be optimized further. This is where SingleInvoker comes in.
@SingleInvoker("modid:event")
private static int singleSumEvent(int i) {
return singleSumEvent(i) + i;
}I would suggest you make SingleInvokers private, and it's required that SingleInvokers exist in the same class as the regular invoker. At runtime, if there is only one listener for an event, the bytecode from the single invoker is copy pasted (overriding the invoker bytecode) and all shallow recursive calls are replaced with a listener call. You're not meant to call the single invoker, you still call the invoker like normal, NanoEvents will handle the copying of bytecode for you. Unlike invokers, there is no Logic#start or Logic#end