diff --git a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt index 8aac2820..038bf3ab 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( @@ -16,13 +14,33 @@ abstract class ChainedRunnablePart( 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( + noinline exceptionHandler: ((E) -> Unit)? = null, + exceptionSync: Boolean = true + ) { + executeCatchingImpl(E::class, exceptionHandler, exceptionSync) + } + + /** + * Has to be public for use in inline function [executeCatching], not + * intended to be used directly. + */ + abstract fun executeCatchingImpl( + exceptionClass: KClass, + exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean ) protected fun start(data: T) { - this.run { + runTask(sync) { val result = invoke(data) next?.start(result) } @@ -31,30 +49,28 @@ abstract class ChainedRunnablePart( protected fun startCatching( data: T, exceptionClass: KClass, - exceptionHandler: ((E) -> Unit)? + exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean ) { - this.run { + runTask(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) { + runTask(exceptionSync) { + exceptionHandler.invoke(e as E) + } + } + return@runTask } else throw e } - if (result != null) - next?.startCatching(result, exceptionClass, exceptionHandler) + next?.startCatching(result, exceptionClass, exceptionHandler, exceptionSync) } } - - private fun run(realRunnable: () -> Unit) { - if (sync) - Bukkit.getScheduler().runTask(KSpigotMainInstance, realRunnable) - else - Bukkit.getScheduler().runTaskAsynchronously(KSpigotMainInstance, realRunnable) - } - } class ChainedRunnablePartFirst( @@ -65,8 +81,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, exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean + ) = + startCatching(Unit, exceptionClass, exceptionHandler, exceptionSync) override fun invoke(data: Unit) = runnable.invoke() @@ -81,8 +100,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, exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean + ) = + previous.executeCatchingImpl(exceptionClass, exceptionHandler, exceptionSync) 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..cedf07fe 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt @@ -104,6 +104,14 @@ fun task( } +fun runTask(sync: Boolean, runnable: () -> Unit) { + if (sync) { + sync(runnable) + } else { + async(runnable) + } +} + /** * Starts a synchronous task. */