Compare commits

...

35 Commits

Author SHA1 Message Date
Shadowfacts 7e582d39ee
Update Kotlin and Coroutines 2019-09-13 16:27:57 -04:00
Shadowfacts 09bd973e77
Fix kotlin-stdlib-jdk7/8 not being shadowed 2019-09-13 16:21:17 -04:00
NikkyAI 85b8fd917b update to 1.3.40 (#60)
* update to 1.3.40-eap

skipped current stable (1.3.31) because of https://youtrack.jetbrains.com/issue/KT-30132

* update to 1.3.40
2019-06-19 15:17:04 -04:00
Shadowfacts 7aa0a3ef37
Bump version 2018-11-24 13:40:33 -05:00
Shadowfacts 1342a6f5a6
Update to Kotlin 1.3.10, Coroutines 1.0.1, and bump version
Closes #48
2018-11-23 21:14:22 -05:00
Shadowfacts b18b818f64
Bump version to 1.8.0 2018-10-30 19:24:05 -04:00
Shadowfacts 90c0276180
Update Kotlin to 1.3.0, Coroutines to 1.0.0
Closes #43
2018-10-30 19:20:59 -04:00
Shadowfacts 583e9d8170
Bump version 2018-06-16 10:34:04 -04:00
Shadowfacts 9809314759
Only attempt to register event handlers for mods that use KotlinAdapter
Closes #41
2018-06-14 19:14:55 -04:00
Shadowfacts 9e8935d4cf
Bump version 2018-06-14 18:25:59 -04:00
Shadowfacts 7b885ea4cd
Convert indents to tabs 2018-06-11 17:22:36 -04:00
Shadowfacts 7cebe692e7
Only unregister static/register object event handlers unless appropriate handler methods are detected 2018-06-11 17:21:43 -04:00
Shadowfacts 26b895b6ce
Bump version 2018-06-10 19:27:52 -04:00
gegy1000 df437491f1 Fix #38 (#39)
Because the automatic subscriber depends on the mod class loader, we need it to run after that has been initialized. That only happens in the construction event, so we have to search at some later stage.
2018-06-10 19:27:26 -04:00
Shadowfacts ecf20f1a76
Don't crash on failed registration
I think Forge is doing something weird with registration event handlers causing ClassNotFoundExceptions

Closes #37
2018-06-09 17:32:39 -04:00
Shadowfacts 5d8ddee776
Update Kotlin 2018-06-09 15:29:04 -04:00
Shadowfacts c64538e7b0
Remove unnecessary elvis operator 2018-06-09 15:28:51 -04:00
Kitten be61809a7b Unregister class reference from the event bus (#36)
When Forgelin registers the object instance of an `@EventBusSubscriber` annotated object class to the event bus, it does not unregister the static class reference that Forge will have registered before Forgelin parses the annotation candidates. This could potentially cause issues, and breaks expectations/semantics from having the annotation register a class both statically and as an instance. This pull request adds a call to `MinecraftForge.EVENT_BUS#unregister` to remove the Forge-registered class reference before registering the instance reference.
2018-06-09 15:08:40 -04:00
gegy1000 438c604d52 Object EventBusSubscriber registration (#34)
* Object EventBusSubscriber registration

* Register from construction and handle companion objects

* Rename construction event listener

* Syntax changes

* Add test mod
2018-05-21 09:36:15 -04:00
Shadowfacts 68c718fe57
Update Maven publishing 2017-11-30 13:31:14 -05:00
Shadowfacts 06f171947d
Update to Kotlin 1.2 2017-11-30 13:26:56 -05:00
Shadowfacts ebba471b4b
Update Gradle config 2017-08-12 17:51:45 -04:00
Marvin Rösch 6f718d74fc Remove custom Kotlin source replacement code (#22) 2017-08-12 17:13:58 -04:00
Marvin Rösch 23dfb368e1 Add automatic version replacement in Forgelin.kt (#20)
* Add automatic version replacement in Forgelin.kt

* Remove unnecessary newlines caused by IDEA
2017-07-19 21:11:55 -04:00
Shadowfacts 8a5751bc19
Update README.md 2017-06-29 16:46:05 -04:00
Shadowfacts bb3a703467
Update Gradle config 2017-06-29 16:39:47 -04:00
Severen Redwood ae873b5cc4 Bump versions (#16)
Bumped the following versions:

- Minecraft (to 1.12)
- Forge (to 14.21.0.2368)
- MCP Mappings (to snapshot_20170624)
- Kotlin (to 1.1.3)
- Kotlin Coroutines (to 0.16)
- Jetbrains Annotations (to 15.0)
2017-06-28 16:48:36 -04:00
Shadowfacts b3fe2d34b3
Bump version 2017-06-11 16:20:08 -04:00
Shadowfacts 2065fbd62b
Add JCenter note to README.md
Closes #14
2017-06-11 16:19:39 -04:00
Shadowfacts 33320699ac
Add mcmod.info
Closes #13
2017-06-11 16:17:46 -04:00
Shadowfacts 469fcdaea7
Update Kotlin and add kotlin-stdlib-jre8
Closes #11
2017-06-11 16:15:54 -04:00
Shadowfacts d5138b9814
Update Kotlin, add JetBrains annotations and Kotlin coroutines
closes #9
2017-04-29 12:05:56 -04:00
Shadowfacts 4dda702c93
Update to Kotlin 1.1.1 & bump version 2017-03-27 16:45:14 -04:00
Shadowfacts 531b3da7ef
Update to Kotlin 1.1
Closes #8
2017-03-05 10:32:02 -05:00
Shadowfacts e0209c61b2
Readd loading plugin
Prevents crash because of unloaded Forgelin/Kotlin classes.

Closes #6
Closes #7
2017-02-16 18:22:08 -05:00
10 changed files with 271 additions and 27 deletions

View File

@ -2,14 +2,15 @@
Fork of [Emberwalker's Forgelin](https://github.com/Emberwalker/Forgelin). Fork of [Emberwalker's Forgelin](https://github.com/Emberwalker/Forgelin).
## Additions ## 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. - Provides a Forge `ILanguageAdapter` for using Kotlin `object` classes as your main mod class.
## Usage ## Usage
```groovy ```groovy
repositories { repositories {
jcenter()
maven { maven {
url "http://mvn.rx14.co.uk/shadowfacts/" url "http://maven.shadowfacts.net/"
} }
} }
@ -18,4 +19,6 @@ dependencies {
} }
``` ```
All versions can be seen [here](http://mvn.rx14.co.uk/shadowfacts/net/shadowfacts/Forgelin/). All versions can be seen [here](http://maven.shadowfacts.net/net/shadowfacts/Forgelin/).
**Note:** You must have the `jcenter()` call in your `repositories` block. JCenter is used to host the Kotlin coroutines libraries.

View File

@ -7,7 +7,7 @@ buildscript {
} }
} }
dependencies { dependencies {
classpath "net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT" classpath "net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}"
} }
} }
@ -17,8 +17,9 @@ plugins {
id "com.github.johnrengelman.shadow" version "1.2.3" id "com.github.johnrengelman.shadow" version "1.2.3"
} }
apply plugin: "net.minecraftforge.gradle.forge"
apply plugin: "kotlin" apply plugin: "kotlin"
apply plugin: "net.minecraftforge.gradle.forge"
apply from: "https://github.com/shadowfacts/maven/raw/master/maven.gradle"
version = mod_version version = mod_version
@ -31,8 +32,7 @@ minecraft {
mappings = mcp_mappings mappings = mcp_mappings
replaceIn "Reference.kt" replaceIn "Forgelin.kt"
replaceIn "Reference.kt"
replace "@VERSION@", mod_version replace "@VERSION@", mod_version
useDepAts = true useDepAts = true
@ -52,30 +52,40 @@ processResources {
} }
repositories { repositories {
maven { jcenter()
name "shadowfacts"
url "http://mvn.rx14.co.uk/shadowfacts/"
}
maven {
url "http://dvs1.progwml6.com/files/maven"
}
maven {
url "http://maven.epoxide.xyz"
}
} }
dependencies { dependencies {
compile group: "org.jetbrains.kotlin", name: "kotlin-stdlib", version: kotlin_version 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.kotlin", name: "kotlin-reflect", version: kotlin_version
compile group: "org.jetbrains.kotlin", name: "kotlin-runtime", version: kotlin_version compile group: "org.jetbrains", name: "annotations", version: annotations_version
compile group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-core", version: coroutines_version
compile group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-jdk8", version: coroutines_version
}
jar {
manifest {
attributes "FMLCorePlugin": "net.shadowfacts.forgelin.preloader.ForgelinPlugin",
"FMLCorePluginContainsFMLMod": "true"
}
} }
shadowJar { shadowJar {
classifier = "" classifier = ""
dependencies { dependencies {
include(dependency("org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}")) 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.kotlin:kotlin-reflect:${kotlin_version}"))
include(dependency("org.jetbrains.kotlin:kotlin-runtime:${kotlin_version}")) include(dependency("org.jetbrains:annotations:${annotations_version}"))
include(dependency("org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutines_version}"))
include(dependency("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:${coroutines_version}"))
}
manifest {
attributes "FMLCorePlugin": "net.shadowfacts.forgelin.preloader.ForgelinPlugin",
"FMLCorePluginContainsFMLMod": "true"
} }
} }
@ -92,3 +102,5 @@ reobf {
} }
tasks.reobfShadowJar.mustRunAfter shadowJar tasks.reobfShadowJar.mustRunAfter shadowJar
tasks.build.dependsOn reobfShadowJar tasks.build.dependsOn reobfShadowJar

View File

@ -1,9 +1,11 @@
mod_version = 1.3.0 mod_version = 1.8.4
group = net.shadowfacts group = net.shadowfacts
archivesBaseName = Forgelin archivesBaseName = Forgelin
mc_version = 1.10.2 mc_version = 1.12.2
mcp_mappings = snapshot_20160802 mcp_mappings = snapshot_20180609
forge_version = 12.18.1.2045 forge_version = 14.23.4.2705
kotlin_version = 1.0.6 kotlin_version = 1.3.50
annotations_version = 16.0.3
coroutines_version = 1.3.1

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists 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

View File

@ -0,0 +1,37 @@
package net.shadowfacts.forgelin.preloader;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
import java.util.Map;
/**
* @author shadowfacts
*/
public class ForgelinPlugin implements IFMLLoadingPlugin {
@Override
public String[] getASMTransformerClass() {
return new String[0];
}
@Override
public String getModContainerClass() {
return null;
}
@Override
public String getSetupClass() {
return "net.shadowfacts.forgelin.preloader.ForgelinSetup";
}
@Override
public void injectData(Map<String, Object> data) {
}
@Override
public String getAccessTransformerClass() {
return null;
}
}

View File

@ -0,0 +1,28 @@
package net.shadowfacts.forgelin.preloader;
import net.minecraftforge.fml.relauncher.IFMLCallHook;
import java.util.Map;
/**
* @author shadowfacts
*/
public class ForgelinSetup implements IFMLCallHook {
@Override
public void injectData(Map<String, Object> data) {
ClassLoader loader = (ClassLoader)data.get("classLoader");
try {
loader.loadClass("net.shadowfacts.forgelin.KotlinAdapter");
} catch (ClassNotFoundException e) {
// this should never happen
throw new RuntimeException("Couldn't find Forgelin langague adapter, this shouldn't be happening", e);
}
}
@Override
public Void call() throws Exception {
return null;
}
}

View File

@ -1,6 +1,10 @@
package net.shadowfacts.forgelin package net.shadowfacts.forgelin
import net.minecraftforge.fml.common.FMLCommonHandler
import net.minecraftforge.fml.common.Loader
import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod
import net.minecraftforge.fml.common.Mod.EventHandler
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent
/** /**
* @author shadowfacts * @author shadowfacts
@ -10,6 +14,12 @@ object Forgelin {
const val MOD_ID = "forgelin" const val MOD_ID = "forgelin"
const val NAME = "Forgelin" const val NAME = "Forgelin"
const val VERSION = "1.3.0" const val VERSION = "@VERSION@"
@EventHandler
fun onPreInit(event: FMLPreInitializationEvent) {
Loader.instance().modList.forEach {
ForgelinAutomaticEventSubscriber.subscribeAutomatic(it, event.asmData, FMLCommonHandler.instance().side)
}
}
} }

View File

@ -0,0 +1,112 @@
package net.shadowfacts.forgelin
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.fml.common.Loader
import net.minecraftforge.fml.common.LoaderException
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 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 unregistered = mutableSetOf<Class<*>>()
private val registered = mutableSetOf<Any>()
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 loader = Loader.instance().modClassLoader
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("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
}
}

View File

@ -0,0 +1,14 @@
[
{
"modid": "forgelin",
"name": "Shadowfacts' Forgelin",
"version": "$version",
"mcversion": "$mcversion",
"description": "Kotlin helper library for Forge.",
"credits": "Emberwalker, for the original Forgelin",
"url": "https://github.com/shadowfacts/Forgelin",
"updateUrl": "",
"authorList": [ "shadowfacts" ],
"screenshots": []
}
]

View File

@ -0,0 +1,26 @@
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
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@Mod(modid = AutomaticKtSubscriberTest.MODID, modLanguageAdapter = "net.shadowfacts.forgelin.KotlinAdapter")
object AutomaticKtSubscriberTest {
const val MODID = "ktsubtest"
@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")
}
}
}