Automatic event subscriber fixed
This commit is contained in:
parent
b5b0402d51
commit
1ab90f9cc3
|
@ -97,8 +97,7 @@ class FMLKotlinModContainer(
|
|||
}
|
||||
|
||||
log.debug(LOADING, "Injecting Automatic event subscribers for {}", getModId())
|
||||
AutomaticEventSubscriber.inject(this, this.scanResults, this.modClass.classLoader)
|
||||
//ForgelinAutomaticEventSubscriber.subscribeAutomatic(FMLKotlinModLoadingContext.get().activeContainer, event.asmData, FMLCommonHandler.instance().side)
|
||||
ForgelinAutomaticEventSubscriber.inject(this, this.scanResults, this.modClass.classLoader)
|
||||
log.debug(LOADING, "Completed Automatic event subscribers for {}", getModId())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,112 +1,55 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
/*import net.minecraftforge.fml.common.Loader
|
||||
import net.minecraftforge.fml.common.LoaderException
|
||||
import net.minecraftforge.api.distmarker.Dist
|
||||
import net.minecraftforge.fml.Logging
|
||||
import net.minecraftforge.fml.ModContainer
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.common.ModContainer
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData
|
||||
import net.minecraftforge.fml.common.discovery.asm.ModAnnotation.EnumHolder
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
|
||||
import net.minecraftforge.fml.relauncher.Side*/
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.EnumSet
|
||||
import kotlin.reflect.full.companionObjectInstance
|
||||
import org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
import java.util.stream.Collectors
|
||||
|
||||
object ForgelinAutomaticEventSubscriber {
|
||||
/*private val DEFAULT_SUBSCRIPTION_SIDES = EnumSet.allOf(Side::class.java)
|
||||
private val LOGGER = LogManager.getLogger(ForgelinAutomaticEventSubscriber::class.java)
|
||||
private val AUTO_SUBSCRIBER = Type.getType(Mod.EventBusSubscriber::class.java)
|
||||
|
||||
private val unregistered = mutableSetOf<Class<*>>()
|
||||
private val registered = mutableSetOf<Any>()
|
||||
private val logger = LogManager.getLogger()
|
||||
|
||||
fun subscribeAutomatic(mod: ModContainer, asm: ASMDataTable, currentSide: Side) {
|
||||
val modAnnotations = asm.getAnnotationsFor(mod) ?: return
|
||||
fun inject(mod: ModContainer, scanData: ModFileScanData?, loader: ClassLoader) {
|
||||
if(scanData == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val containedMods = modAnnotations.get(Mod::class.java.name)
|
||||
val subscribers = modAnnotations.get(Mod.EventBusSubscriber::class.java.name)
|
||||
.filter { parseTargetSides(it).contains(currentSide) }
|
||||
logger.debug(Logging.LOADING, "Attempting to inject @EventBusSubscriber classes into the eventbus for {}", mod.modId)
|
||||
val targets = scanData.annotations.stream()
|
||||
.filter { annotationData -> annotationData.annotationType == AUTO_SUBSCRIBER }
|
||||
.filter { annotationData -> shouldBeRegistered(mod.modId, annotationData) }
|
||||
.collect(Collectors.toList())
|
||||
|
||||
val loader = Loader.instance().modClassLoader
|
||||
targets.forEach { ad ->
|
||||
val busTargetHolder = ad.annotationData.getOrDefault("bus", ModAnnotation.EnumHolder(null, "FORGE")) as ModAnnotation.EnumHolder
|
||||
val busTarget = Mod.EventBusSubscriber.Bus.valueOf(busTargetHolder.value)
|
||||
|
||||
try {
|
||||
logger.debug(Logging.LOADING, "Auto-subscribing {} to {}", ad.classType.className, busTarget)
|
||||
val className = Class.forName(ad.classType.className, true, loader)
|
||||
busTarget.bus().get().register(className.kotlin.objectInstance ?: className)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
logger.fatal(Logging.LOADING, "Failed to load mod class {} for @EventBusSubscriber annotation", ad.classType, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (containedMod in containedMods) {
|
||||
val containedModId = containedMod.annotationInfo["modid"] as String
|
||||
if (containedMod.annotationInfo["modLanguageAdapter"] != FMLKotlinModLanguageProvider::class.qualifiedName) {
|
||||
LOGGER.debug("Skipping @EventBusSubscriber injection for {} since it does not use FMLKotlinModLanguageProvider", containedModId)
|
||||
continue
|
||||
}
|
||||
private fun shouldBeRegistered(modId: String, ad: ModFileScanData.AnnotationData): Boolean {
|
||||
val sidesValue = ad.annotationData.getOrDefault("value", Arrays.asList(ModAnnotation.EnumHolder(null, "CLIENT"), ModAnnotation.EnumHolder(null, "DEDICATED_SERVER"))) as List<ModAnnotation.EnumHolder>
|
||||
val sides = sidesValue.stream()
|
||||
.map { eh -> Dist.valueOf(eh.value) }
|
||||
.collect(Collectors.toCollection { EnumSet.noneOf(Dist::class.java) }) as EnumSet<Dist>
|
||||
val annotationModId = ad.annotationData.getOrDefault("modid", modId) as String
|
||||
|
||||
LOGGER.debug("Attempting to register Kotlin @EventBusSubscriber objects for {}", containedModId)
|
||||
|
||||
for (subscriber in subscribers) {
|
||||
try {
|
||||
val ownerModId = parseModId(containedMods, subscriber)
|
||||
if (ownerModId.isNullOrEmpty()) {
|
||||
LOGGER.debug("Could not determine owning mod for @EventBusSubscriber on {} for mod {}", subscriber.className, mod.modId)
|
||||
continue
|
||||
}
|
||||
|
||||
if (containedModId != ownerModId) {
|
||||
LOGGER.debug("Skipping @EventBusSubscriber injection for {} since it is not for mod {}", subscriber.className, containedModId)
|
||||
continue
|
||||
}
|
||||
|
||||
val subscriberClass = Class.forName(subscriber.className, false, loader) ?: continue
|
||||
val kotlinClass = subscriberClass.kotlin
|
||||
val objectInstance = kotlinClass.objectInstance ?: kotlinClass.companionObjectInstance ?: continue
|
||||
|
||||
if (!hasStaticEventHandlers(subscriberClass) && subscriberClass !in unregistered) {
|
||||
MinecraftForge.EVENT_BUS.unregister(subscriberClass)
|
||||
unregistered += subscriberClass
|
||||
LOGGER.debug("Unregistered static @EventBusSubscriber class {}", subscriber.className)
|
||||
}
|
||||
if (hasObjectEventHandlers(objectInstance) && objectInstance !in registered) {
|
||||
MinecraftForge.EVENT_BUS.register(objectInstance)
|
||||
registered += objectInstance
|
||||
LOGGER.debug("Registered @EventBusSubscriber object instance {}", subscriber.className)
|
||||
}
|
||||
|
||||
} catch (e: Throwable) {
|
||||
LOGGER.error("An error occurred trying to load an @EventBusSubscriber object {} for modid {}", mod.modId, e)
|
||||
throw LoaderException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasObjectEventHandlers(objectInstance: Any): Boolean {
|
||||
return objectInstance.javaClass.methods.any {
|
||||
!Modifier.isStatic(it.modifiers) && it.isAnnotationPresent(SubscribeEvent::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasStaticEventHandlers(clazz: Class<*>): Boolean {
|
||||
return clazz.methods.any {
|
||||
Modifier.isStatic(it.modifiers) && it.isAnnotationPresent(SubscribeEvent::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseModId(containedMods: MutableSet<ASMData>, subscriber: ASMData): String? {
|
||||
val parsedModId: String? = subscriber.annotationInfo["modid"] as? String
|
||||
if (parsedModId.isNullOrEmpty()) {
|
||||
return parsedModId
|
||||
}
|
||||
|
||||
return ASMDataTable.getOwnerModID(containedMods, subscriber)
|
||||
}
|
||||
|
||||
private fun parseTargetSides(subscriber: ASMData): EnumSet<Side> {
|
||||
val parsedSides: List<EnumHolder>? = subscriber.annotationInfo["value"] as? List<EnumHolder>
|
||||
if (parsedSides != null) {
|
||||
val targetSides = EnumSet.noneOf(Side::class.java)
|
||||
for (parsed in parsedSides) {
|
||||
targetSides.add(Side.valueOf(parsed.value))
|
||||
}
|
||||
return targetSides
|
||||
}
|
||||
return DEFAULT_SUBSCRIPTION_SIDES
|
||||
}*/
|
||||
return modId == annotationModId && sides.contains(FMLEnvironment.dist)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,15 @@ object ForgelinTest {
|
|||
FMLKotlinModLoadingContext.get().modEventBus.register(this)
|
||||
}
|
||||
|
||||
// You can also use EventBusSubscriber as usual
|
||||
@Mod.EventBusSubscriber
|
||||
object EventSubscriber {
|
||||
@SubscribeEvent
|
||||
fun testNonStatic(event: EntityJoinWorldEvent) {
|
||||
logger.info("HELLO from testNonStatic")
|
||||
}
|
||||
}
|
||||
|
||||
fun setup(event: FMLCommonSetupEvent) {
|
||||
logger.info("HELLO from setup")
|
||||
}
|
||||
|
@ -32,19 +41,4 @@ object ForgelinTest {
|
|||
fun setup3(event: FMLCommonSetupEvent) {
|
||||
logger.info("HELLO from setup3")
|
||||
}
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
object EventSubscriber {
|
||||
// doesn't work
|
||||
@SubscribeEvent
|
||||
fun testNonStatic(event: EntityJoinWorldEvent) {
|
||||
logger.info("HELLO from testNonStatic")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@SubscribeEvent
|
||||
fun testStatic(event: EntityJoinWorldEvent) {
|
||||
logger.info("HELLO from testStatic")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue