diff options
author | thedarkcolour <30441001+thedarkcolour@users.noreply.github.com> | 2021-02-01 10:36:32 -0800 |
---|---|---|
committer | thedarkcolour <30441001+thedarkcolour@users.noreply.github.com> | 2021-02-01 10:36:32 -0800 |
commit | 28214d92042f0a4673f53699b1ff52af0226ccb3 (patch) | |
tree | 615ee3e17759e407cbe8451c7ff6d7af4f871411 /src | |
parent | 668b5c35ea900750c35f2ea8d878c1c5e6a04607 (diff) | |
download | KotlinForForge-28214d92042f0a4673f53699b1ff52af0226ccb3.tar.gz KotlinForForge-28214d92042f0a4673f53699b1ff52af0226ccb3.tar.bz2 KotlinForForge-28214d92042f0a4673f53699b1ff52af0226ccb3.zip |
Kotlin for Forge 1.8.0
Diffstat (limited to 'src')
7 files changed, 121 insertions, 73 deletions
diff --git a/src/main/java/net/minecraftforge/fml/event/lifecycle/IModBusEvent.java b/src/main/java/net/minecraftforge/fml/event/lifecycle/IModBusEvent.java new file mode 100644 index 0000000..22ebb57 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/event/lifecycle/IModBusEvent.java @@ -0,0 +1,4 @@ +package net.minecraftforge.fml.event.lifecycle; + +// Make things compile +public interface IModBusEvent {} diff --git a/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinForForge.kt b/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinForForge.kt index 168d3f0..fac6ed6 100644 --- a/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinForForge.kt +++ b/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinForForge.kt @@ -1,7 +1,12 @@ package thedarkcolour.kotlinforforge +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.event.entity.player.AdvancementEvent import net.minecraftforge.fml.common.Mod +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext +import thedarkcolour.kotlinforforge.forge.FORGE_BUS +import thedarkcolour.kotlinforforge.forge.MOD_BUS /** * Set `modLoader` in mods.toml to @@ -14,4 +19,14 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext * check out the [KotlinModdingSkeleton repository](https://github.com/thedarkcolour/KotlinModdingSkeleton). */ @Mod("kotlinforforge") -public object KotlinForForge
\ No newline at end of file +public object KotlinForForge { + init { + MOD_BUS.addListener { event: FMLLoadCompleteEvent -> + val a = FORGE_BUS.post(AdvancementEvent(null, null)) + val b = MinecraftForge.EVENT_BUS.post(AdvancementEvent(null, null)) + + println("POST TEST: $a") + println("POST TEST: $b") + } + } +}
\ No newline at end of file diff --git a/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinModContainer.kt b/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinModContainer.kt index db61225..7208cc6 100644 --- a/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinModContainer.kt +++ b/src/main/kotlin/thedarkcolour/kotlinforforge/KotlinModContainer.kt @@ -5,21 +5,20 @@ import net.minecraftforge.eventbus.api.BusBuilder import net.minecraftforge.eventbus.api.Event import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.eventbus.api.IEventListener -import net.minecraftforge.fml.LifecycleEventProvider.LifecycleEvent import net.minecraftforge.fml.Logging import net.minecraftforge.fml.ModContainer import net.minecraftforge.fml.ModLoadingException import net.minecraftforge.fml.ModLoadingStage import net.minecraftforge.fml.config.ModConfig +import net.minecraftforge.fml.event.lifecycle.IModBusEvent import net.minecraftforge.forgespi.language.IModInfo import net.minecraftforge.forgespi.language.ModFileScanData import thedarkcolour.kotlinforforge.eventbus.KotlinEventBus import thedarkcolour.kotlinforforge.kotlin.supply +import java.lang.IllegalArgumentException import java.lang.reflect.Field import java.util.function.Consumer -public typealias LifecycleEventListener = (LifecycleEvent) -> Unit - /** * The Kotlin for Forge `ModContainer`. */ @@ -41,7 +40,7 @@ public class KotlinModContainer( */ public val eventBus: KotlinEventBus - private val _triggerMap: MutableMap<ModLoadingStage, Consumer<LifecycleEvent>>? + private val _triggerMap: MutableMap<ModLoadingStage, Any>? private val _activityMap: MutableMap<ModLoadingStage, Runnable>? init { @@ -53,7 +52,7 @@ public class KotlinModContainer( } @Suppress("UNCHECKED_CAST") _triggerMap = try { - TRIGGER_MAP_FIELD?.get(this) as MutableMap<ModLoadingStage, Consumer<LifecycleEvent>> + TRIGGER_MAP_FIELD?.get(this) as MutableMap<ModLoadingStage, Any> } catch (e: Exception) { null } @@ -63,15 +62,7 @@ public class KotlinModContainer( if (_activityMap != null) { _activityMap[ModLoadingStage.CONSTRUCT] = Runnable(::constructMod) } else if (_triggerMap != null) { - _triggerMap[ModLoadingStage.CONSTRUCT] = createTrigger( { constructMod() }, ::afterEvent) - _triggerMap[ModLoadingStage.CREATE_REGISTRIES] = createTrigger(::fireEvent, ::afterEvent) - _triggerMap[ModLoadingStage.LOAD_REGISTRIES] = createTrigger(::fireEvent, ::afterEvent) - _triggerMap[ModLoadingStage.COMMON_SETUP] = createTrigger(::fireEvent, ::afterEvent) - _triggerMap[ModLoadingStage.SIDED_SETUP] = createTrigger(::fireEvent, ::afterEvent) - _triggerMap[ModLoadingStage.ENQUEUE_IMC] = createTrigger(::fireEvent, ::afterEvent) - _triggerMap[ModLoadingStage.PROCESS_IMC] = createTrigger(::fireEvent, ::afterEvent) - _triggerMap[ModLoadingStage.COMPLETE] = createTrigger(::fireEvent, ::afterEvent) - _triggerMap[ModLoadingStage.GATHERDATA] = createTrigger(::fireEvent, ::afterEvent) + setupTriggerMap(_triggerMap) } eventBus = KotlinEventBus(BusBuilder.builder().setExceptionHandler(::onEventFailed).setTrackPhases(false)) @@ -79,61 +70,20 @@ public class KotlinModContainer( } /** - * Creates a single `Consumer` that calls - * both [consumerA] and [consumerB]. - */ - private fun createTrigger( - consumerA: LifecycleEventListener, - consumerB: LifecycleEventListener, - ): Consumer<LifecycleEvent> { - return Consumer { event -> - consumerA(event) - consumerB(event) - } - } - - /** * The `IEventExceptionHandler` that logs * errors in events as errors. */ private fun onEventFailed( - iEventBus: IEventBus, - event: Event, - iEventListeners: Array<IEventListener>, - i: Int, - throwable: Throwable + iEventBus: IEventBus, + event: Event, + iEventListeners: Array<IEventListener>, + i: Int, + throwable: Throwable, ) { LOGGER.error(EventBusErrorMessage(event, i, iEventListeners, throwable)) } /** - * Fires a `LifecycleEvent` on the mod [eventBus]. - */ - private fun fireEvent(lifecycleEvent: LifecycleEvent) { - val event = lifecycleEvent.getOrBuildEvent(this) - - LOGGER.debug(Logging.LOADING, "Firing event for modid $modId : $event") - - try { - eventBus.post(event) - LOGGER.debug(Logging.LOADING, "Fired event for modid $modId : $event") - } catch (throwable: Throwable) { - LOGGER.error(Logging.LOADING, "An error occurred while dispatching event ${lifecycleEvent.fromStage()} to $modId") - throw ModLoadingException(modInfo, lifecycleEvent.fromStage(), "fml.modloading.errorduringevent", throwable) - } - } - - /** - * If an error was thrown during the event, - * log it to the console as an error. - */ - private fun afterEvent(lifecycleEvent: LifecycleEvent) { - if (currentState == ModLoadingStage.ERROR) { - LOGGER.error(Logging.LOADING, "An error occurred while dispatching event ${lifecycleEvent.fromStage()} to $modId") - } - } - - /** * Initializes [modInstance] and calls the mod constructor */ private fun constructMod() { @@ -177,7 +127,7 @@ public class KotlinModContainer( override fun getMod(): Any = modInstance - override fun acceptEvent(e: Event) { + public override fun <T> acceptEvent(e: T) where T : Event, T : IModBusEvent { try { LOGGER.debug("Firing event for modid $modId : $e") eventBus.post(e) @@ -188,6 +138,50 @@ public class KotlinModContainer( } } + public fun setupTriggerMap(map: MutableMap<ModLoadingStage, Any>) { + map[ModLoadingStage.CONSTRUCT] = createTrigger( { constructMod() }, ::afterEvent) + map[ModLoadingStage.CREATE_REGISTRIES] = createTrigger(::fireEvent, ::afterEvent) + map[ModLoadingStage.LOAD_REGISTRIES] = createTrigger(::fireEvent, ::afterEvent) + map[ModLoadingStage.COMMON_SETUP] = createTrigger(::fireEvent, ::afterEvent) + map[ModLoadingStage.SIDED_SETUP] = createTrigger(::fireEvent, ::afterEvent) + map[ModLoadingStage.ENQUEUE_IMC] = createTrigger(::fireEvent, ::afterEvent) + map[ModLoadingStage.PROCESS_IMC] = createTrigger(::fireEvent, ::afterEvent) + map[ModLoadingStage.COMPLETE] = createTrigger(::fireEvent, ::afterEvent) + try { + map[ModLoadingStage.valueOf("GATHERDATA")] = createTrigger(::fireEvent, ::afterEvent) + } catch (e: IllegalArgumentException) {} + } + + private fun afterEvent(lifecycleEvent: Any) { + if (currentState == ModLoadingStage.ERROR) { + LOGGER.error(Logging.LOADING, "An error occurred while dispatching event ${fromStageMethod!!.invoke(lifecycleEvent)} to ${getModId()}") + } + } + + private fun fireEvent(lifecycleEvent: Any) { + val event = getOrBuildEventMethod!!.invoke(lifecycleEvent, this) as Event + + LOGGER.debug(Logging.LOADING, "Firing event for modid ${getModId()} : $event") + + try { + eventBus.post(event) + LOGGER.debug(Logging.LOADING, "Fired event for modid ${getModId()} : $event") + } catch (throwable: Throwable) { + LOGGER.error(Logging.LOADING, "An error occurred while dispatching event ${fromStageMethod!!.invoke(lifecycleEvent)} to ${getModId()}") + throw ModLoadingException(getModInfo(), fromStageMethod.invoke(lifecycleEvent) as ModLoadingStage, "fml.modloading.errorduringevent", throwable) + } + } + + private fun createTrigger( + consumerA: (Any) -> Unit, + consumerB: (Any) -> Unit, + ): Consumer<Any> { + return Consumer { event -> + consumerA(event) + consumerB(event) + } + } + private companion object { private val TRIGGER_MAP_FIELD: Field? = try { ModContainer::class.java.getDeclaredField("triggerMap").also { field -> @@ -203,5 +197,12 @@ public class KotlinModContainer( } catch (e: NoSuchFieldException) { null } + + private val getOrBuildEventMethod = try { + Class.forName("net.minecraftforge.fml.LifecycleEventProvider\$LifecycleEvent").getDeclaredMethod("getOrBuildEvent", ModContainer::class.java) + } catch (e: ClassNotFoundException) { null } catch (e: NoSuchMethodError) { null } + private val fromStageMethod = try { + Class.forName("net.minecraftforge.fml.LifecycleEventProvider\$LifecycleEvent").getDeclaredMethod("fromStage") + } catch (e: ClassNotFoundException) { null } catch (e: NoSuchMethodError) { null } } }
\ No newline at end of file diff --git a/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/IKotlinEventBus.kt b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/IKotlinEventBus.kt new file mode 100644 index 0000000..e26c002 --- /dev/null +++ b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/IKotlinEventBus.kt @@ -0,0 +1,22 @@ +package thedarkcolour.kotlinforforge.eventbus + +import net.minecraftforge.eventbus.api.Event +import net.minecraftforge.eventbus.api.IEventBus +import net.minecraftforge.eventbus.api.IEventBusInvokeDispatcher +import net.minecraftforge.eventbus.api.IEventListener + +/** @since 1.7.1 + * Maintain compatibility between old versions of event bus. + */ +public interface IKotlinEventBus : IEventBus { + /** + * Implement by default so classloading [KotlinEventBus] + * does not try to load [IEventBusInvokeDispatcher]. + */ + @JvmDefault + override fun post(event: Event, wrapper: IEventBusInvokeDispatcher): Boolean { + return post(wrapper::invoke, event) + } + + public fun post(wrapper: (IEventListener, Event) -> Unit, event: Event): Boolean +}
\ No newline at end of file diff --git a/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt index 3f3fb66..a3580e6 100644 --- a/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt +++ b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBus.kt @@ -22,7 +22,7 @@ import java.util.function.Consumer * @param builder The BusBuilder used to configure this event bus * @param synthetic Whether this event bus is just a wrapper for another bus */ -public open class KotlinEventBus(builder: BusBuilder, synthetic: Boolean = false) : IEventBus, IEventExceptionHandler { +public open class KotlinEventBus(builder: BusBuilder, synthetic: Boolean = false) : IKotlinEventBus, IEventExceptionHandler { @Suppress("LeakingThis") private val exceptionHandler = builder.exceptionHandler ?: this private val trackPhases = builder.trackPhases @@ -31,6 +31,7 @@ public open class KotlinEventBus(builder: BusBuilder, synthetic: Boolean = false protected open val busID: Int = MAX_ID.getAndIncrement() protected open val listeners: ConcurrentHashMap<Any, MutableList<IEventListener>> = ConcurrentHashMap() + init { // see companion object if (!synthetic) { @@ -365,6 +366,10 @@ public open class KotlinEventBus(builder: BusBuilder, synthetic: Boolean = false } override fun post(event: Event): Boolean { + return post(IEventListener::invoke, event) + } + + override fun post(wrapper: (IEventListener, Event) -> Unit, event: Event): Boolean { if (shutdown) return false val listeners = event.listenerList.getListeners(busID) @@ -374,7 +379,7 @@ public open class KotlinEventBus(builder: BusBuilder, synthetic: Boolean = false if (!trackPhases && listeners[index]::class.java == EventPriority::class.java) { continue } else { - listeners[index].invoke(event) + wrapper.invoke(listeners[index], event) } } catch (throwable: Throwable) { exceptionHandler.handleException(this, event, listeners, index, throwable) diff --git a/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBusWrapper.kt b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBusWrapper.kt index ac12b1b..dee96b6 100644 --- a/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBusWrapper.kt +++ b/src/main/kotlin/thedarkcolour/kotlinforforge/eventbus/KotlinEventBusWrapper.kt @@ -1,10 +1,7 @@ package thedarkcolour.kotlinforforge.eventbus import net.minecraftforge.eventbus.EventBus -import net.minecraftforge.eventbus.api.BusBuilder -import net.minecraftforge.eventbus.api.IEventBus -import net.minecraftforge.eventbus.api.IEventExceptionHandler -import net.minecraftforge.eventbus.api.IEventListener +import net.minecraftforge.eventbus.api.* import thedarkcolour.kotlinforforge.forge.FORGE_BUS import java.util.concurrent.ConcurrentHashMap @@ -13,13 +10,17 @@ import java.util.concurrent.ConcurrentHashMap * when using [FORGE_BUS]. */ public class KotlinEventBusWrapper(private val parent: EventBus) : KotlinEventBus(BusBuilder() - .setExceptionHandler(getExceptionHandler(parent)) - .setTrackPhases(getTrackPhases(parent)) - .also { if (getShutdown(parent)) it.startShutdown() } + .setExceptionHandler(getExceptionHandler(parent)) + .setTrackPhases(getTrackPhases(parent)) + .also { if (getShutdown(parent)) it.startShutdown() } ) { override val busID: Int = getBusID(parent) override val listeners: ConcurrentHashMap<Any, MutableList<IEventListener>> = getListeners(parent) + override fun post(event: Event): Boolean { + return parent.post(event) + } + // reflection stuff private companion object { private val GET_BUS_ID = EventBus::class.java.getDeclaredField("busID").also { it.isAccessible = true } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index e0174e8..370d49c 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,5 +1,5 @@ modLoader="kotlinforforge" # IModLanguageProvider -loaderVersion="[1.6,)" # IModLanguageProvider version +loaderVersion="[1.8,)" # IModLanguageProvider version license="GPL v3.0" # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. @@ -30,7 +30,7 @@ license="GPL v3.0" [[mods]] #mandatory displayName="Kotlin for Forge" # Name of mod modId="kotlinforforge" # Modid -version="1.6.2" # Version of kotlinforforge +version="1.7.1" # Version of kotlinforforge authors="TheDarkColour" # Author credits="Herobrine knows all." # Credits description=''' |