Event Listener

EventService

In Reactant, we are using another way to listen to the events which is slightly different from Bukkit's way. Reactant provided a component called EventService, it can provide the Observable of the Bukkit events.

We have learned how to inject other components at the previous tutorial, it is your turns to try it.

import dev.reactant.reactant.service.spec.server.EventService
@Component
class MyFirstEventHandler(
private val eventService: EventService
) : LifeCycleHook {
override fun onEnable(){
}
}

Event Observable

Now we have got the EventService, let's try to listen to the PlayerEggThrowEvent and send a message to the thrower.

override fun onEnable(){
eventService {
PlayerEggThrowEvent::class.observable().subscribe { event ->
event.player.sendMessage("You throw an egg!")
}
}
}

Event Priority and Ignore Cancelled

eventService {
// High Priority Event Listener
PlayerEggThrowEvent::class.observable(EventPriority.HIGH).subscribe { }
// Ignore Cancelled Event
PlayerEggThrowEvent::class.observable(true).subscribe { }
// Or both
PlayerEggThrowEvent::class.observable(true, EventPriority.HIGH).subscribe { }
}

More about Event Observable

Handling events is annoying, but you can use the operators of Observable of ReactiveX to make your lives easier. If you are wondering what can be done with the operators, check the diagrams from ReactiveX documentation and RxMarble.

Following are some examples for your reference.

Event Filtering

Filter is a useful operator for filtering the events you are interested in.

// Only subscribe to the event if the player is going to sneak
PlayerToggleSneakEvent::class.observable()
.filter { it.isSneaking }
.subscribe { it.palyer.sendMessage("Fart!") }

Simple Cooldown

Some time we want to make a cooldown time for the skills. With ReactiveX, we can easily create an elegant solution to count the cooldown.

Following is an example to make 10 seconds cooldown for each fart ;D

  1. Group the observable by the player, so that each player has its own sneak event observable.
  2. Map for each grouped observables: only
  3. For each grouped observables, throttle first event for each 10 second, then flatMap will flatten the grouped observables into single observable
PlayerToggleSneakEvent::class.observable()
.filter { it.isSneaking }
.groupBy { it.player }
.flatMap { it.throttleFirst(10, TimeUnit.SECONDS) }
.subscribe { it.player.sendMessage("Fart!") }