import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.eventbus.api.Event
import net.minecraftforge.eventbus.api.EventPriority
import net.minecraftforge.eventbus.api.GenericEvent
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.fml.event.IModBusEvent
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext
import net.minecraftforge.registries.DeferredRegister
import org.apache.http.util.Asserts
object Dispatcher {
val modBus get() = FMLJavaModLoadingContext.get().modEventBus!!
val forgeBus get() = MinecraftForge.EVENT_BUS!!
@JvmName("registerForNoneGenericEvent")
inline operator fun <reified T : GenericEvent<out V>, reified V : Any> invoke(crossinline codeBlock: (T) -> Unit) {
invoke<T, V>(EventPriority.NORMAL, false, codeBlock)
}
@JvmName("registerForNoneGenericEvent")
inline operator fun <reified T : GenericEvent<out V>, reified V : Any> invoke(
priority: EventPriority = EventPriority.NORMAL,
receiveCanceled: Boolean = false,
crossinline codeBlock: (T) -> Unit,
) {
Asserts.check(T::class.java.isGenericEvent(), "${T::class.java.simpleName} is not GenericEvent<T>")
switchEvent<T>().addGenericListener(
V::class.java, priority, receiveCanceled, T::class.java
) { e -> codeBlock(e) }
}
@JvmName("registerForGenericEvent")
inline operator fun <reified T : Event> invoke(crossinline codeBlock: (T) -> Unit) {
invoke<T>(EventPriority.NORMAL, false, codeBlock)
}
@JvmName("registerForGenericEvent")
inline operator fun <reified T : Event> invoke(
priority: EventPriority = EventPriority.NORMAL,
receiveCanceled: Boolean = false,
crossinline codeBlock: (T) -> Unit,
) {
Asserts.check(!T::class.java.isGenericEvent(), "${T::class.java.simpleName} is GenericEvent<T>")
switchEvent<T>().addListener(priority, receiveCanceled, T::class.java) { e -> codeBlock.invoke(e) }
}
fun <T : DeferredRegister<*>> registerDeferred(register: T) {
register.register(modBus)
}
@PublishedApi
internal fun <T> Class<T>.isGenericEvent() = GenericEvent::class.java.isAssignableFrom(this)
@PublishedApi
internal fun <T> Class<T>.isModEvent() = IModBusEvent::class.java.isAssignableFrom(this)
@PublishedApi
internal inline fun <reified T : Event> switchEvent(): IEventBus {
return when {
T::class.java.isModEvent() -> modBus
else -> forgeBus
}
}
}for example
fun test(dispatcher: Dispatcher) {
//for none-GenericEvent
dispatcher<FMLClientSetupEvent> { event ->
}
dispatcher<_, _> { event: FMLClientSetupEvent ->
//compile error
}
//for GenericEvent
dispatcher<_, _> { event: AttachCapabilitiesEvent<LevelChunk> ->
}
dispatcher<AttachCapabilitiesEvent<LevelChunk>, _> { event ->
}
dispatcher<_> { event: AttachCapabilitiesEvent<LevelChunk> ->
//cause runtime check error
}
}