diff --git a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt index 8aac2820..3f3f9c4f 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt @@ -2,8 +2,6 @@ package net.axay.kspigot.runnables -import net.axay.kspigot.main.KSpigotMainInstance -import org.bukkit.Bukkit import kotlin.reflect.KClass abstract class ChainedRunnablePart( @@ -14,15 +12,38 @@ abstract class ChainedRunnablePart( protected abstract fun invoke(data: T): R + /** + * Begins execution of this chained runnable. + */ abstract fun execute() - abstract fun executeCatching( - @Suppress("UNCHECKED_CAST") exceptionClass: KClass = Exception::class as KClass, - exceptionHandler: ((E) -> Unit)? = null + /** + * Begins execution of this chained runnable, catching any exception of + * type [E] and passing it to the optional [exceptionHandler]. + * + * @param exceptionSync whether the exception handler should be executed + * synchronously or asynchronously, defaults to `true` (Note that usage of + * any Spigot API functions requires it to be sync) + */ + inline fun executeCatching( + exceptionSync: Boolean = true, + noinline exceptionHandler: ((E) -> Unit)? = null + ) { + executeCatchingImpl(E::class, exceptionSync, exceptionHandler) + } + + /** + * Has to be public for use in inline function [executeCatching], not + * intended to be used directly. + */ + abstract fun executeCatchingImpl( + exceptionClass: KClass, + exceptionSync: Boolean, + exceptionHandler: ((E) -> Unit)?, ) protected fun start(data: T) { - this.run { + bukkitRun(sync) { val result = invoke(data) next?.start(result) } @@ -31,30 +52,29 @@ abstract class ChainedRunnablePart( protected fun startCatching( data: T, exceptionClass: KClass, - exceptionHandler: ((E) -> Unit)? + exceptionSync: Boolean, + exceptionHandler: ((E) -> Unit)?, ) { - this.run { + bukkitRun(sync) { val result = try { invoke(data) } catch (e: Exception) { if (exceptionClass.isInstance(e)) { @Suppress("UNCHECKED_CAST") - exceptionHandler?.invoke(e as E) - null + if (sync == exceptionSync) { + exceptionHandler?.invoke(e as E) + } else if (exceptionHandler != null) { + bukkitRun(exceptionSync) { + exceptionHandler.invoke(e as E) + } + } + return@bukkitRun } else throw e } - if (result != null) - next?.startCatching(result, exceptionClass, exceptionHandler) + next?.startCatching(result, exceptionClass, exceptionSync, exceptionHandler) } } - private fun run(realRunnable: () -> Unit) { - if (sync) - Bukkit.getScheduler().runTask(KSpigotMainInstance, realRunnable) - else - Bukkit.getScheduler().runTaskAsynchronously(KSpigotMainInstance, realRunnable) - } - } class ChainedRunnablePartFirst( @@ -65,8 +85,11 @@ class ChainedRunnablePartFirst( override fun execute() = start(Unit) - override fun executeCatching(exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?) - = startCatching(Unit, exceptionClass, exceptionHandler) + override fun executeCatchingImpl( + exceptionClass: KClass, + exceptionSync: Boolean, + exceptionHandler: ((E) -> Unit)? + ) = startCatching(Unit, exceptionClass, exceptionSync, exceptionHandler) override fun invoke(data: Unit) = runnable.invoke() @@ -81,8 +104,11 @@ class ChainedRunnablePartThen( override fun execute() = previous.execute() - override fun executeCatching(exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?) - = previous.executeCatching(exceptionClass, exceptionHandler) + override fun executeCatchingImpl( + exceptionClass: KClass, + exceptionSync: Boolean, + exceptionHandler: ((E) -> Unit)? + ) = previous.executeCatchingImpl(exceptionClass, exceptionSync, exceptionHandler) override fun invoke(data: T) = runnable.invoke(data) diff --git a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt index 8a3ebb10..b9f51f1e 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt @@ -104,6 +104,18 @@ fun task( } +/** + * Executes the given [runnable] either + * sync or async (specified by the [sync] parameter). + */ +fun bukkitRun(sync: Boolean, runnable: () -> Unit) { + if (sync) { + sync(runnable) + } else { + async(runnable) + } +} + /** * Starts a synchronous task. */