Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 7e582d39ee | |
Shadowfacts | 09bd973e77 | |
NikkyAI | 85b8fd917b | |
Shadowfacts | 7aa0a3ef37 | |
Shadowfacts | 1342a6f5a6 | |
Shadowfacts | b18b818f64 | |
Shadowfacts | 90c0276180 | |
Shadowfacts | 583e9d8170 | |
Shadowfacts | 9809314759 | |
Shadowfacts | 9e8935d4cf | |
Shadowfacts | 7b885ea4cd | |
Shadowfacts | 7cebe692e7 | |
Shadowfacts | 26b895b6ce | |
gegy1000 | df437491f1 |
|
@ -2,7 +2,7 @@
|
|||
Fork of [Emberwalker's Forgelin](https://github.com/Emberwalker/Forgelin).
|
||||
|
||||
## Additions
|
||||
- Shades the Kotlin standard library, runtime, and reflect libraries so you don't have to.
|
||||
- Shades the Kotlin standard library, runtime, coroutines-core, and reflect libraries so you don't have to.
|
||||
- Provides a Forge `ILanguageAdapter` for using Kotlin `object` classes as your main mod class.
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -57,6 +57,7 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
compile group: "org.jetbrains.kotlin", name: "kotlin-stdlib", version: kotlin_version
|
||||
compile group: "org.jetbrains.kotlin", name: "kotlin-stdlib-jdk7", version: kotlin_version
|
||||
compile group: "org.jetbrains.kotlin", name: "kotlin-stdlib-jdk8", version: kotlin_version
|
||||
compile group: "org.jetbrains.kotlin", name: "kotlin-reflect", version: kotlin_version
|
||||
compile group: "org.jetbrains", name: "annotations", version: annotations_version
|
||||
|
@ -75,6 +76,8 @@ shadowJar {
|
|||
classifier = ""
|
||||
dependencies {
|
||||
include(dependency("org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"))
|
||||
include(dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlin_version}"))
|
||||
include(dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"))
|
||||
include(dependency("org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}"))
|
||||
include(dependency("org.jetbrains:annotations:${annotations_version}"))
|
||||
include(dependency("org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutines_version}"))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
mod_version = 1.7.1
|
||||
mod_version = 1.8.4
|
||||
group = net.shadowfacts
|
||||
archivesBaseName = Forgelin
|
||||
|
||||
|
@ -6,6 +6,6 @@ mc_version = 1.12.2
|
|||
mcp_mappings = snapshot_20180609
|
||||
forge_version = 14.23.4.2705
|
||||
|
||||
kotlin_version = 1.2.41
|
||||
annotations_version = 16.0.2
|
||||
coroutines_version = 0.23.0
|
||||
kotlin_version = 1.3.50
|
||||
annotations_version = 16.0.3
|
||||
coroutines_version = 1.3.1
|
||||
|
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
|
||||
|
|
|
@ -4,7 +4,7 @@ import net.minecraftforge.fml.common.FMLCommonHandler
|
|||
import net.minecraftforge.fml.common.Loader
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.common.Mod.EventHandler
|
||||
import net.minecraftforge.fml.common.event.FMLConstructionEvent
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -17,9 +17,9 @@ object Forgelin {
|
|||
const val VERSION = "@VERSION@"
|
||||
|
||||
@EventHandler
|
||||
fun onConstruction(event: FMLConstructionEvent) {
|
||||
fun onPreInit(event: FMLPreInitializationEvent) {
|
||||
Loader.instance().modList.forEach {
|
||||
ForgelinAutomaticEventSubscriber.subscribeAutomatic(it, event.asmHarvestedData, FMLCommonHandler.instance().side)
|
||||
ForgelinAutomaticEventSubscriber.subscribeAutomatic(it, event.asmData, FMLCommonHandler.instance().side)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,72 +8,105 @@ 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 org.apache.logging.log4j.LogManager
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.EnumSet
|
||||
import kotlin.reflect.full.companionObjectInstance
|
||||
|
||||
object ForgelinAutomaticEventSubscriber {
|
||||
private val DEFAULT_SUBSCRIPTION_SIDES = EnumSet.allOf(Side::class.java)
|
||||
private val LOGGER = LogManager.getLogger(ForgelinAutomaticEventSubscriber::class.java)
|
||||
private val DEFAULT_SUBSCRIPTION_SIDES = EnumSet.allOf(Side::class.java)
|
||||
private val LOGGER = LogManager.getLogger(ForgelinAutomaticEventSubscriber::class.java)
|
||||
|
||||
fun subscribeAutomatic(mod: ModContainer, asm: ASMDataTable, currentSide: Side) {
|
||||
LOGGER.debug("Attempting to register Kotlin @EventBusSubscriber objects for {}", mod.modId)
|
||||
private val unregistered = mutableSetOf<Class<*>>()
|
||||
private val registered = mutableSetOf<Any>()
|
||||
|
||||
val modAnnotations = asm.getAnnotationsFor(mod) ?: return
|
||||
fun subscribeAutomatic(mod: ModContainer, asm: ASMDataTable, currentSide: Side) {
|
||||
val modAnnotations = asm.getAnnotationsFor(mod) ?: return
|
||||
|
||||
val containedMods = modAnnotations.get(Mod::class.java.name)
|
||||
val subscribers = modAnnotations.get(Mod.EventBusSubscriber::class.java.name)
|
||||
.filter { parseTargetSides(it).contains(currentSide) }
|
||||
val containedMods = modAnnotations.get(Mod::class.java.name)
|
||||
val subscribers = modAnnotations.get(Mod.EventBusSubscriber::class.java.name)
|
||||
.filter { parseTargetSides(it).contains(currentSide) }
|
||||
|
||||
val loader = Loader.instance().modClassLoader
|
||||
val loader = Loader.instance().modClassLoader
|
||||
|
||||
for (subscriber in subscribers) {
|
||||
try {
|
||||
val ownerModId = parseModId(containedMods, subscriber)
|
||||
if (ownerModId.isNullOrEmpty()) {
|
||||
LOGGER.warn("Could not determine owning mod for @EventBusSubscriber on {} for mod {}", subscriber.className, mod.modId)
|
||||
continue
|
||||
}
|
||||
|
||||
if (mod.modId != ownerModId) {
|
||||
LOGGER.debug("Skipping @EventBusSubscriber injection for {} since it is not for mod {}", subscriber.className, mod.modId)
|
||||
continue
|
||||
}
|
||||
for (containedMod in containedMods) {
|
||||
val containedModId = containedMod.annotationInfo["modid"] as String
|
||||
if (containedMod.annotationInfo["modLanguageAdapter"] != KotlinAdapter::class.qualifiedName) {
|
||||
LOGGER.debug("Skipping @EventBusSubscriber injection for {} since it does not use KotlinAdapter", containedModId)
|
||||
continue
|
||||
}
|
||||
|
||||
LOGGER.debug("Registering @EventBusSubscriber object for {} for mod {}", subscriber.className, mod.modId)
|
||||
LOGGER.debug("Attempting to register Kotlin @EventBusSubscriber objects for {}", containedModId)
|
||||
|
||||
val subscriberClass = Class.forName(subscriber.className, false, loader) ?: continue
|
||||
val kotlinClass = subscriberClass.kotlin
|
||||
val subscriberInstance = kotlinClass.objectInstance ?: kotlinClass.companionObjectInstance ?: continue
|
||||
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
|
||||
}
|
||||
|
||||
MinecraftForge.EVENT_BUS.unregister(subscriberClass)
|
||||
MinecraftForge.EVENT_BUS.register(subscriberInstance)
|
||||
LOGGER.debug("Registered @EventBusSubscriber object {}", subscriber.className)
|
||||
} catch (e: Throwable) {
|
||||
LOGGER.error("An error occurred trying to load an @EventBusSubscriber object {} for modid {}", mod.modId, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (containedModId != ownerModId) {
|
||||
LOGGER.debug("Skipping @EventBusSubscriber injection for {} since it is not for mod {}", subscriber.className, containedModId)
|
||||
continue
|
||||
}
|
||||
|
||||
private fun parseModId(containedMods: MutableSet<ASMData>, subscriber: ASMData): String? {
|
||||
val parsedModId: String? = subscriber.annotationInfo["modid"] as? String
|
||||
if (parsedModId.isNullOrEmpty()) {
|
||||
return parsedModId
|
||||
}
|
||||
val subscriberClass = Class.forName(subscriber.className, false, loader) ?: continue
|
||||
val kotlinClass = subscriberClass.kotlin
|
||||
val objectInstance = kotlinClass.objectInstance ?: kotlinClass.companionObjectInstance ?: continue
|
||||
|
||||
return ASMDataTable.getOwnerModID(containedMods, subscriber)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber
|
||||
|
@ -7,13 +8,19 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
|
|||
|
||||
@Mod(modid = AutomaticKtSubscriberTest.MODID, modLanguageAdapter = "net.shadowfacts.forgelin.KotlinAdapter")
|
||||
object AutomaticKtSubscriberTest {
|
||||
const val MODID = "ktsubtest"
|
||||
const val MODID = "ktsubtest"
|
||||
|
||||
@EventBusSubscriber(modid = AutomaticKtSubscriberTest.MODID)
|
||||
object EventSubscriber {
|
||||
@SubscribeEvent
|
||||
fun onRightClickBlock(event: RightClickBlock) {
|
||||
println("Automatic KT subscriber: Right click ${event.pos}")
|
||||
}
|
||||
}
|
||||
@EventBusSubscriber(modid = AutomaticKtSubscriberTest.MODID)
|
||||
object EventSubscriber {
|
||||
@SubscribeEvent
|
||||
fun onRightClickBlock(event: RightClickBlock) {
|
||||
println("Automatic KT subscriber: Right click ${event.pos}")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@SubscribeEvent
|
||||
fun onRightClickItem(event: PlayerInteractEvent.RightClickItem) {
|
||||
println("Right click item")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue