Conor Gould
11/18/2023, 3:39 PMMap<String, List<(Event) -> Unit>>
, and then I have this function that adds a lambda into the map:
inline fun <reified T : Event> T.subscribe( handler: (T) -> Unit) {
EventManager.handlers.getOrPut(T::class.simpleName!!, mutableListOf<(T) -> Unit>())
}
The problem is is that I am getting this error:
Type mismatch.
Required:
() → TypeVariable(V)
Found:
MutableList<(T) → Unit>
Even though I declare T
as a subclass of Event
. Is this intended behavior?Daniel Pitts
11/18/2023, 3:57 PMConor Gould
11/18/2023, 4:23 PMDaniel Pitts
11/18/2023, 4:23 PMConor Gould
11/18/2023, 4:23 PMDaniel Pitts
11/18/2023, 4:29 PMimport kotlin.reflect.KClass
typealias Handler<T> = (T) -> Unit
typealias HandlerList<T> = MutableList<Handler<T>>
interface Event
class EventManager {
private val handlers: MutableMap<KClass<*>, HandlerList<*>> = mutableMapOf()
inline fun <reified T : Event> subscribe(noinline handler: Handler<T>) = subscribe(T::class, handler)
fun <T : Event> subscribe(kClass: KClass<T>, handler: Handler<T>) {
handlers.computeIfAbsent(kClass) { mutableListOf() }.add(handler)
}
inline fun <reified T : Event> dispatch(event: T) = dispatch(T::class, event)
fun <T : Event> dispatch(kClass: KClass<T>, event: T) =
handlerList(kClass).forEach { handler -> handler(event) }
@Suppress("UNCHECKED_CAST")
private fun <T : Event> handlerList(kClass: KClass<T>): List<Handler<T>> =
handlers[kClass] as? HandlerList<T> ?: emptyList()
}
Conor Gould
11/18/2023, 4:29 PMMutableMap#getOrPut
takes (K, () -> V)
Daniel Pitts
11/18/2023, 4:29 PMConor Gould
11/18/2023, 4:30 PMDaniel Pitts
11/18/2023, 4:31 PMConor Gould
11/18/2023, 4:32 PMinline fun <T : Event> T.subscribe(handler: (T) -> Unit) {
EventManager.handlers.getOrPut(this::class.simpleName!!) { mutableListOf() }
}
Daniel Pitts
11/18/2023, 4:34 PMConor Gould
11/18/2023, 5:05 PMcompanion object
to a java class.Daniel Pitts
11/18/2023, 5:06 PM@JvmStatic
to create static methods though.Conor Gould
11/18/2023, 5:07 PMOnly members in named objects and companion objects can be annotated with '@JvmStatic'
Oliver Eisenbarth
11/18/2023, 9:01 PMDaniel Pitts
11/18/2023, 9:01 PMConor Gould
11/19/2023, 1:18 AM@EventHandler
, but that's ugly and unintuative. I was going to make an object
that subscribes to all of the events that are possible to subscribe to, and then iterate through the handlers for that event and call each one. This would allow you to, instead of using an entire class/file, use one line of code to handle an event.Daniel Pitts
11/19/2023, 1:21 AMConor Gould
11/19/2023, 1:22 AMEvent.subscribe { println("event called" }
instead of class EventHandler : Listener { @EventHandler fun onEvent(event: Event) { println("event called" } }
Daniel Pitts
11/19/2023, 1:24 AMsubscribe<Event> { println("event called") }
Conor Gould
11/19/2023, 1:25 AMDaniel Pitts
11/19/2023, 1:29 AMsubscribe
implementation.object DefaultListener : Listener
inline fun <reified E : Event> Plugin.subscribe(
priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false,
crossinline handler: (E) -> Unit
) {
pluginManager.registerEvent(
E::class.java, DefaultListener, priority,
object : EventExecutor {
override fun execute(listener: Listener, event: Event) {
handler(event as E)
}
},
this,
ignoreCancelled
)
}
subscribe<SomeEvent> { println(it) }
it
is the SomeEvent object. This also lets you override the priority and the ignoreCancelled, just like you can with the annotation.Conor Gould
11/19/2023, 3:45 AMEventManager.subscribe<BlockBreakEvent> { event ->
}
EventManager
as a listener for every event. Generated ~3k lines of code.Daniel Pitts
11/19/2023, 3:47 AMConor Gould
11/19/2023, 3:48 AMDaniel Pitts
11/19/2023, 3:48 AMConor Gould
11/19/2023, 3:48 AMDaniel Pitts
11/19/2023, 3:49 AMConor Gould
11/19/2023, 3:49 AMhandlers[event.eventName]?.forEach { it(event) }