-
Notifications
You must be signed in to change notification settings - Fork 21
Events
Events are the building blocks for all of Void's content; they are used for transmitting information between entities and content in handlers. Events fall into two types: Notifications which are events sent to all handlers, and Interactions which are sent only to the first handler.
Each event has a list of parameters which are unique values used lookup handlers. At minimum one parameter must be specified and typically the first parameter is a uniquely identifable name such as the event's class name in lower underscore case.
class TestEvent(val id: String) : Event {
override val size = 1
override fun parameter(dispatcher: EventDispatcher, index: Int) {
return when (index) {
0 -> "test_event"
1 -> id
else -> null
}
}
}
Any number of parameters can be used, however it's recommended to use as few as necessary (< 5).
Events can be emitted from anywhere using the singleton Events.events.emit(dispatcher, events)
but they are sent alongside an EventDispatcher which represents the Entity the event was emitted from.
As events are so commonly emitted from Entities, there is a Entity.emit(event)
method to help keep code clean:
player.emit(TestEvent(id = 11))
Handlers are code which is executed everytime an event with matching parameters is emitted.
Not all parameters must match exactly, the star glyph *
can be used as a wildcard to match part of a string i.e. "amulet_of_glory_*", or by itself will act as a default and match all values, including non-strings nulls.
Events.handle<Player, TestEvent>("test_event", 4) { player ->
player.message("Test number four.")
}
In this example the player will be sent a message only when the event emitted has an id
of 4.
Events.handle<Player, TestEvent>("test_event", "*") { player ->
player.message("Test number: $id")
}
The above example will handle all TestEvent's regardless of what id
they have.
Warning
If both handlers are present and an event has an id
of 4, only the handler matching 4 will be executed TestEvent.notification = false
even though the second match matches all ids, an exact match will be matched first.
Often times you'll want to handle the same event being emitted from different Entities, in these cases the entity type can be added to the class name using dispatcher.key
. The entities id can also be added as a parameter with dispatcher.identifier
.
data class VariableSet(
val key: String,
val from: Any?,
val to: Any?
) : Event {
override val size = 5
override fun parameter(dispatcher: EventDispatcher, index: Int) = when (index) {
0 -> "${dispatcher.key}_set_variable" // Adding the dispatcher type to the name makes it more readable
1 -> key
2 -> dispatcher.identifier
3 -> from
4 -> to
else -> null
}
}
// parameters can be of any comparable types
fun variableSet(id: String = "*", from: Any? = "*", to: Any? = "*", handler: suspend VariableSet.(Player) -> Unit) {
// "player" is used in place of the entitiy id as players don't have ids
Events.handle("player_set_variable", id, "player", from, to, handler = handler)
}
fun npcVariableSet(npc: String = "*", variable: String = "*", from: Any? = "*", to: Any? = "*", handler: suspend VariableSet.(NPC) -> Unit) {
// by passing an npc id we can (optionally) match the source npcs name as well as the variable and it's values
Events.handle("npc_set_variable", variable, npc, from, to, handler = handler)
}