Rewrite for 1.13 (wip)
This commit is contained in:
parent
22eb8db077
commit
2cc508fd38
|
@ -1,37 +0,0 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.eventbus.EventBusErrorMessage
|
||||
import net.minecraftforge.eventbus.api.Event
|
||||
import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.eventbus.api.IEventExceptionHandler
|
||||
import net.minecraftforge.eventbus.api.IEventListener
|
||||
import net.minecraftforge.fml.*
|
||||
import net.minecraftforge.fml.Logging.LOADING
|
||||
import net.minecraftforge.fml.config.ModConfig
|
||||
import net.minecraftforge.forgespi.language.IModInfo
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
|
||||
class FMLKotlinModContainer(
|
||||
private val info: IModInfo,
|
||||
private val className: String,
|
||||
private val modClassLoader: ClassLoader,
|
||||
private val scanResults: ModFileScanData
|
||||
) : ModContainer(info) {
|
||||
private val log = LogManager.getLogger()
|
||||
|
||||
val eventBus: IEventBus
|
||||
private var mod: Any? = null
|
||||
private val modClass: Class<*>
|
||||
|
||||
init {
|
||||
log.debug(LOADING, "Creating FMLModContainer instance for {} with classLoader {} & {}", className, modClassLoader, javaClass.classLoader)
|
||||
triggerMap[ModLoadingStage.CONSTRUCT] = dummy().andThen(::beforeEvent).andThen(::constructMod).andThen(::afterEvent)
|
||||
triggerMap[ModLoadingStage.CREATE_REGISTRIES] = dummy().andThen(::beforeEvent).andThen(::fireEvent).andThen(::afterEvent)
|
||||
triggerMap[ModLoadingStage.LOAD_REGISTRIES] = dummy().andThen(::beforeEvent).andThen(::fireEvent).andThen(::afterEvent)
|
||||
triggerMap[ModLoadingStage.COMMON_SETUP] = dummy().andThen(::beforeEvent).andThen(::fireEvent).andThen(::afterEvent)
|
||||
triggerMap[ModLoadingStage.SIDED_SETUP] = dummy().andThen(::beforeEvent).andThen(::fireEvent).andThen(::afterEvent)
|
||||
triggerMap[ModLoadingStage.ENQUEUE_IMC] = dummy().andThen(::beforeEvent).andThen(::fireEvent).andThen(::afterEvent)
|
||||
triggerMap[ModLoadingStage.PROCESS_IMC] = dummy().andThen(::beforeEvent).andThen(::fireEvent).andThen(::afterEvent)
|
||||
triggerMap[ModLoadingStage.COMPLETE] = dummy().andThen(::beforeEvent).andThen(::fireEvent).andThen(::afterEvent)
|
||||
eventBus = IEventBus.create(::onEventFailed)
|
||||
configHandler = Optional.of<Consumer<ModConfig.ModConfigEvent>>(Consumer { event -> eventBus.post(event) })
|
||||
|
||||
try {
|
||||
// Here, we won't init the class, meaning static {} blocks (init {} in kotlin) won't get triggered
|
||||
// but we will still have to do it later, on CONSTRUCT phase.
|
||||
modClass = Class.forName(className, false, modClassLoader)
|
||||
log.debug(LOADING, "Loaded modclass {} with {}", modClass.name, modClass.classLoader)
|
||||
} catch (e: Throwable) {
|
||||
log.error(LOADING, "Failed to load class {}", className, e)
|
||||
throw ModLoadingException(info, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmodclass", e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun dummy(): Consumer<LifecycleEventProvider.LifecycleEvent> = Consumer {}
|
||||
|
||||
private fun onEventFailed(iEventBus: IEventBus, event: Event, iEventListeners: Array<IEventListener>, i: Int, throwable: Throwable) {
|
||||
log.error(EventBusErrorMessage(event, i, iEventListeners, throwable))
|
||||
}
|
||||
|
||||
private fun beforeEvent(lifecycleEvent: LifecycleEventProvider.LifecycleEvent) {
|
||||
FMLKotlinModLoadingContext.get().activeContainer = this
|
||||
ModThreadContext.get().activeContainer = this
|
||||
}
|
||||
|
||||
private fun fireEvent(lifecycleEvent: LifecycleEventProvider.LifecycleEvent) {
|
||||
val event = lifecycleEvent.getOrBuildEvent(this)
|
||||
log.debug(LOADING, "Firing event for modid {} : {}", this.getModId(), event)
|
||||
try {
|
||||
eventBus.post(event)
|
||||
log.debug(LOADING, "Fired event for modid {} : {}", this.getModId(), event)
|
||||
} catch (e: Throwable) {
|
||||
log.error(LOADING, "Caught exception during event {} dispatch for modid {}", event, this.getModId(), e)
|
||||
throw ModLoadingException(modInfo, lifecycleEvent.fromStage(), "fml.modloading.errorduringevent", e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun afterEvent(lifecycleEvent: LifecycleEventProvider.LifecycleEvent) {
|
||||
ModThreadContext.get().activeContainer = null
|
||||
FMLKotlinModLoadingContext.get().activeContainer = null
|
||||
if (currentState == ModLoadingStage.ERROR) {
|
||||
log.error(LOADING, "An error occurred while dispatching event {} to {}", lifecycleEvent.fromStage(), getModId())
|
||||
}
|
||||
}
|
||||
|
||||
private fun constructMod(event: LifecycleEventProvider.LifecycleEvent) {
|
||||
try {
|
||||
log.debug(LOADING, "Loading mod instance {} of type {}", getModId(), modClass.name)
|
||||
// Now we can load the class, so that static {} block gets called
|
||||
Class.forName(className)
|
||||
// Then we check whether it's a kotlin object and return it, or if not we create a new instance of kotlin class.
|
||||
this.mod = modClass.kotlin.objectInstance ?: modClass.newInstance()
|
||||
log.debug(LOADING, "Loaded mod instance {} of type {}", getModId(), modClass.name)
|
||||
} catch (e: Throwable) {
|
||||
log.error(LOADING, "Failed to create mod instance. ModID: {}, class {}", getModId(), modClass.name, e)
|
||||
throw ModLoadingException(modInfo, event.fromStage(), "fml.modloading.failedtoloadmod", e, modClass)
|
||||
}
|
||||
|
||||
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)
|
||||
log.debug(LOADING, "Completed Automatic event subscribers for {}", getModId())
|
||||
}
|
||||
|
||||
override fun matches(mod: Any): Boolean = mod === this.mod
|
||||
|
||||
override fun getMod(): Any? = mod
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.fml.Logging.SCAN
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLanguageProvider
|
||||
import net.minecraftforge.forgespi.language.ILifecycleEvent
|
||||
import net.minecraftforge.forgespi.language.IModLanguageProvider
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Supplier
|
||||
import java.util.stream.Collectors
|
||||
|
||||
/**
|
||||
* Forge {@link ILanguageAdapter} for Kotlin
|
||||
* Usage: Set the {@code modLanguageAdapter} field in your {@code @Mod} annotation to {@code net.shadowfacts.forgelin.FMLKotlinModLanguageProvider}
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class FMLKotlinModLanguageProvider : IModLanguageProvider {
|
||||
private val log = LogManager.getLogger()
|
||||
|
||||
override fun name(): String {
|
||||
return "kotlinfml"
|
||||
}
|
||||
|
||||
override fun getFileVisitor(): Consumer<ModFileScanData> {
|
||||
return Consumer { scanResult ->
|
||||
val modTargetMap = scanResult.annotations.stream()
|
||||
.filter { ad -> ad.annotationType == FMLJavaModLanguageProvider.MODANNOTATION }
|
||||
.peek { ad -> log.debug(SCAN, "Found @Mod class {} with id {}", ad.classType.className, ad.annotationData["value"]) }
|
||||
.map { ad -> FMLKotlinModTarget(ad.classType.className, ad.annotationData["value"] as String) }
|
||||
.collect(Collectors.toMap(java.util.function.Function<FMLKotlinModTarget, String> { it.modId }, java.util.function.Function.identity<FMLKotlinModTarget>()))
|
||||
scanResult.addLanguageLoader(modTargetMap)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <R : ILifecycleEvent<R>?> consumeLifecycleEvent(consumeEvent: Supplier<R>?) {}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.fml.ExtensionPoint
|
||||
import net.minecraftforge.fml.config.ModConfig
|
||||
import java.util.function.Supplier
|
||||
|
||||
object FMLKotlinModLoadingContext {
|
||||
private val context = ThreadLocal.withInitial { FMLKotlinModLoadingContext }
|
||||
var activeContainer: FMLKotlinModContainer? = null
|
||||
|
||||
val modEventBus: IEventBus
|
||||
get() = activeContainer!!.eventBus
|
||||
|
||||
fun get(): FMLKotlinModLoadingContext {
|
||||
return context.get()
|
||||
}
|
||||
|
||||
fun <T> registerExtensionPoint(point: ExtensionPoint<T>, extension: Supplier<T>) {
|
||||
activeContainer!!.registerExtensionPoint(point, extension)
|
||||
}
|
||||
|
||||
fun registerConfig(type: ModConfig.Type, spec: ForgeConfigSpec) {
|
||||
activeContainer!!.addConfig(ModConfig(type, spec, activeContainer!!))
|
||||
}
|
||||
|
||||
fun registerConfig(type: ModConfig.Type, spec: ForgeConfigSpec, fileName: String) {
|
||||
activeContainer!!.addConfig(ModConfig(type, spec, activeContainer, fileName))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.fml.Logging.LOADING
|
||||
import net.minecraftforge.forgespi.language.IModInfo
|
||||
import net.minecraftforge.forgespi.language.IModLanguageProvider
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
class FMLKotlinModTarget(private val className: String, val modId: String) : IModLanguageProvider.IModLanguageLoader {
|
||||
private val log = LogManager.getLogger()
|
||||
|
||||
override fun <T> loadMod(info: IModInfo, modClassLoader: ClassLoader, modFileScanResults: ModFileScanData): T {
|
||||
// This language class is loaded in the system level classloader - before the game even starts
|
||||
// So we must treat container construction as an arms length operation, and load the container
|
||||
// in the classloader of the game - the context classloader is appropriate here.
|
||||
try {
|
||||
val fmlContainer = Class.forName("net.shadowfacts.forgelin.FMLKotlinModContainer", true, Thread.currentThread().contextClassLoader)
|
||||
log.debug(LOADING, "Loading FMLKotlinModContainer from classloader {} - got {}", Thread.currentThread().contextClassLoader, fmlContainer.classLoader)
|
||||
val constructor = fmlContainer.getConstructor(IModInfo::class.java, String::class.java, ClassLoader::class.java, ModFileScanData::class.java)
|
||||
return constructor.newInstance(info, className, modClassLoader, modFileScanResults) as T
|
||||
} catch (e: ReflectiveOperationException) {
|
||||
log.fatal(LOADING, "Unable to load FMLKotlinModContainer, wut?", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,6 @@
|
|||
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.EventHandler
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
@Mod(modid = Forgelin.MOD_ID, name = Forgelin.NAME, version = Forgelin.VERSION, acceptableRemoteVersions = "*", acceptedMinecraftVersions = "*", modLanguageAdapter = "net.shadowfacts.forgelin.KotlinAdapter")
|
||||
object Forgelin {
|
||||
|
||||
const val MOD_ID = "forgelin"
|
||||
const val NAME = "Forgelin"
|
||||
const val VERSION = "@VERSION@"
|
||||
|
||||
@EventHandler
|
||||
fun onPreInit(event: FMLPreInitializationEvent) {
|
||||
Loader.instance().modList.forEach {
|
||||
ForgelinAutomaticEventSubscriber.subscribeAutomatic(it, event.asmData, FMLCommonHandler.instance().side)
|
||||
}
|
||||
}
|
||||
}
|
||||
@Mod("forgelin")
|
||||
object Forgelin
|
|
@ -1,7 +1,7 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.fml.common.Loader
|
||||
/*import net.minecraftforge.fml.common.Loader
|
||||
import net.minecraftforge.fml.common.LoaderException
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.common.ModContainer
|
||||
|
@ -9,14 +9,14 @@ 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.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 DEFAULT_SUBSCRIPTION_SIDES = EnumSet.allOf(Side::class.java)
|
||||
private val LOGGER = LogManager.getLogger(ForgelinAutomaticEventSubscriber::class.java)
|
||||
|
||||
private val unregistered = mutableSetOf<Class<*>>()
|
||||
|
@ -34,8 +34,8 @@ object ForgelinAutomaticEventSubscriber {
|
|||
|
||||
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)
|
||||
if (containedMod.annotationInfo["modLanguageAdapter"] != FMLKotlinModLanguageProvider::class.qualifiedName) {
|
||||
LOGGER.debug("Skipping @EventBusSubscriber injection for {} since it does not use FMLKotlinModLanguageProvider", containedModId)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -108,5 +108,5 @@ object ForgelinAutomaticEventSubscriber {
|
|||
return targetSides
|
||||
}
|
||||
return DEFAULT_SUBSCRIPTION_SIDES
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.fml.common.FMLModContainer
|
||||
import net.minecraftforge.fml.common.ILanguageAdapter
|
||||
import net.minecraftforge.fml.common.ModContainer
|
||||
import net.minecraftforge.fml.relauncher.Side
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* Forge {@link ILanguageAdapter} for Kotlin
|
||||
* Usage: Set the {@code modLanguageAdapter} field in your {@code @Mod} annotation to {@code net.shadowfacts.forgelin.KotlinAdapter}
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class KotlinAdapter : ILanguageAdapter {
|
||||
|
||||
private val log = LogManager.getLogger("KotlinAdapter")
|
||||
|
||||
override fun supportsStatics(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun setProxy(target: Field, proxyTarget: Class<*>, proxy: Any) {
|
||||
log.debug("Setting proxy: ${target.declaringClass.simpleName}.${target.name} -> $proxy")
|
||||
|
||||
// objectInstance is not null if it's a Kotlin object, so set the value on the object
|
||||
// if it is null, set the value on the static field
|
||||
target.set(proxyTarget.kotlin.objectInstance, proxy)
|
||||
}
|
||||
|
||||
override fun getNewInstance(container: FMLModContainer, objectClass: Class<*>, classLoader: ClassLoader, factoryMarkedAnnotation: Method?): Any {
|
||||
log.debug("FML has asked for ${objectClass.simpleName} to be constructed")
|
||||
return objectClass.kotlin.objectInstance ?: objectClass.newInstance()
|
||||
}
|
||||
|
||||
override fun setInternalProxies(mod: ModContainer?, side: Side?, loader: ClassLoader?) {
|
||||
// Nothing to do; FML's got this covered for Kotlin
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
# This is an example mods.toml file. It contains the data relating to the loading mods.
|
||||
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
|
||||
# The overall format is standard TOML format, v0.5.0.
|
||||
# Note that there are a couple of TOML lists in this file.
|
||||
# Find more information on toml format here: https://github.com/toml-lang/toml
|
||||
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
|
||||
modLoader="kotlinfml" #mandatory
|
||||
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
|
||||
loaderVersion="[24,)" #mandatory (24 is current forge version)
|
||||
# A URL to refer people to when problems occur with this mod
|
||||
issueTrackerURL="https://github.com/shadowfacts/Forgelin/issues" #optional
|
||||
# A URL for the "homepage" for this mod, displayed in the mod UI
|
||||
displayURL="https://github.com/shadowfacts/Forgelin" #optional
|
||||
# A file name (in the root of the mod JAR) containing a logo for display
|
||||
logoFile="examplemod.png" #optional
|
||||
# A text field displayed in the mod UI
|
||||
credits="Emberwalker, for the original Forgelin" #optional
|
||||
# A text field displayed in the mod UI
|
||||
authors="shadowfacts" #optional
|
||||
# A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
# The modid of the mod
|
||||
modId="forgelin" #mandatory
|
||||
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
version="${file.jarVersion}" #mandatory
|
||||
# A display name for the mod
|
||||
displayName="Shadowfacts' Forgelin" #mandatory
|
||||
# A URL to query for updates for this mod. See the JSON update specification <here>
|
||||
#updateJSONURL="" #optional
|
||||
# The description text for the mod (multi line!) (#mandatory)
|
||||
description='''
|
||||
Kotlin provider for Forge.
|
||||
'''
|
||||
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
|
||||
[[dependencies.forgelin]] #optional
|
||||
# the modid of the dependency
|
||||
modId="forge" #mandatory
|
||||
# Does this dependency have to exist - if not, ordering below must be specified
|
||||
mandatory=true #mandatory
|
||||
# The version range of the dependency
|
||||
versionRange="[24,)" #mandatory
|
||||
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
|
||||
ordering="NONE"
|
||||
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
||||
side="BOTH"
|
||||
# Here's another dependency
|
||||
[[dependencies.forgelin]]
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
versionRange="[1.13]"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
|
@ -0,0 +1 @@
|
|||
net.shadowfacts.forgelin.FMLKotlinModLanguageProvider
|
|
@ -1,14 +0,0 @@
|
|||
[
|
||||
{
|
||||
"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": []
|
||||
}
|
||||
]
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"pack": {
|
||||
"description": "Forgelin resources",
|
||||
"pack_format": 4,
|
||||
"_comment": "Without this file, Forge crashes on startup."
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
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")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package net.shadowfacts.forgelin
|
||||
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
|
||||
@Mod("forgelin_test")
|
||||
object ForgelinTest {
|
||||
val logger: Logger = LogManager.getLogger()
|
||||
|
||||
init {
|
||||
// You either need to specify generic type explicitly and use a consumer
|
||||
FMLKotlinModLoadingContext.get().modEventBus.addListener<FMLCommonSetupEvent> { setup(it) }
|
||||
// use a consumer with parameter types specified
|
||||
FMLKotlinModLoadingContext.get().modEventBus.addListener { event: FMLCommonSetupEvent -> setup2(event) }
|
||||
// or just register whole object and mark needed method with SubscribeEvent annotations.
|
||||
FMLKotlinModLoadingContext.get().modEventBus.register(this)
|
||||
}
|
||||
|
||||
fun setup(event: FMLCommonSetupEvent) {
|
||||
logger.info("HELLO from setup")
|
||||
}
|
||||
|
||||
fun setup2(event: FMLCommonSetupEvent) {
|
||||
logger.info("HELLO from setup2")
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
modLoader="kotlinfml"
|
||||
loaderVersion="[24,)"
|
||||
issueTrackerURL="https://github.com/shadowfacts/Forgelin/issues"
|
||||
displayURL="https://github.com/shadowfacts/Forgelin"
|
||||
logoFile="examplemod.png"
|
||||
credits="Emberwalker, for the original Forgelin"
|
||||
authors="shadowfacts"
|
||||
|
||||
[[mods]]
|
||||
modId="forgelin_test"
|
||||
version="${file.jarVersion}"
|
||||
displayName="Shadowfacts' Forgelin Test"
|
||||
|
||||
[[dependencies.forgelin_test]]
|
||||
modId="forge"
|
||||
mandatory=true
|
||||
versionRange="[24,)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
|
||||
[[dependencies.forgelin_test]]
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
versionRange="[1.13]"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
|
||||
[[dependencies.forgelin_test]]
|
||||
modId="forgelin"
|
||||
mandatory=true
|
||||
ordering="AFTER"
|
||||
side="BOTH"
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"pack": {
|
||||
"description": "Forgelin test resources",
|
||||
"pack_format": 4,
|
||||
"_comment": "Without this file, Forge crashes on startup."
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue