From d93cda5daef0bf488f81c7ee39a85422d00ffc36 Mon Sep 17 00:00:00 2001 From: bluefireoly Date: Sat, 29 Aug 2020 19:12:25 +0200 Subject: [PATCH] Updated runnable api --- readme.md | 24 +++- .../kspigot/runnables/KSpigotRunnables.kt | 123 +++++++++--------- 2 files changed, 78 insertions(+), 69 deletions(-) diff --git a/readme.md b/readme.md index 5766e535..56069c25 100644 --- a/readme.md +++ b/readme.md @@ -30,21 +30,31 @@ onDisable() with shutdown() ### Simple runnables and schedulers: ```kotlin -bukkitAsync(kSpigot) { /* short form for async schedulers */ } +plugin.async { /* short form for async tasks */ } ``` ```kotlin -bukkitSync(kSpigot) { /* sync some code to bukkits main thread */ } +plugin.sync { /* sync some code to bukkits main thread */ } ``` ```kotlin -bukkitRunnable( - kSpigot, +kSpigot.task( sync = false, - howoften = 5, delay = 25, - period = 20 -) { /* runnable code */ } + period = 20, + howOften = 5 +) { + // runnable code... + + // you can access the following counter variables in here + println(counterUp) // starting from zero + println(counterDown) // starting from howOften +} ``` +NOTE: The counters are nullable, because howOften is (when null) infinite. + +#### Safe runnables + +With the `kSpigot.task() { }` method you have the possibility to set the parameter `safe = true`. When doing this, the defined `endCallback` will be executed under any circumstances (except a major server crash). If you define `endCallback`, but do not set `safe = true` the `endCallback` will only be executed when the task ends, because the limit of `howOften` was reached. ### Powerful builders diff --git a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt index a487e2f2..14bedb41 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt @@ -2,105 +2,104 @@ package net.axay.kspigot.runnables import net.axay.kspigot.main.KSpigot import org.bukkit.Bukkit +import org.bukkit.plugin.Plugin import org.bukkit.scheduler.BukkitRunnable class KRunnableHolder { - val runnableEndCallbacks = HashMap Unit>() + private val runnableEndCallbacks = HashMap Unit>() fun shutdown() { runnableEndCallbacks.values.forEach { it.invoke() } runnableEndCallbacks.clear() } + fun add(runnable: BukkitRunnable, callback: () -> Unit) { runnableEndCallbacks[runnable] = callback } + fun remove(runnable: BukkitRunnable) = runnableEndCallbacks.remove(runnable) + fun activate(runnable: BukkitRunnable) = runnableEndCallbacks.remove(runnable)?.invoke() + } -class KSpigotRunnable( - var counter: Int , - private val runnable: BukkitRunnable? = null -) { - fun cancel() = runnable?.cancel() -} +abstract class KSpigotRunnable( + var counterUp: Long? = null, + var counterDown: Long? = null +) : BukkitRunnable() -fun bukkitRunnable( - kSpigot: KSpigot, +/** + * Starts a new BukkitRunnable. + * + * @param sync if the runnable should run sync (true) or async (false) + * @param howOften how many times the task should be executed - null for infinite execution + * @param delay the delay (in ticks) until the first execution of the task + * @param period at which interval (in ticks) the task should be repeated + * @param safe if the endCallback of the runnable should always be executed, + * even if the server shuts down or the runnable ends prematurely + * @param endCallback code that should always be executed when the runnable ends + * @param runnable the runnable which should be executed each repetition + */ +fun KSpigot.task( sync: Boolean = true, - howoften: Int = 1, - delay: Long? = null, + delay: Long = 0, period: Long? = null, + howOften: Long? = null, safe: Boolean = false, endCallback: (() -> Unit)? = null, runnable: ((KSpigotRunnable) -> Unit)? = null ) { - if (howoften >= 0) return + if (howOften != null && howOften == 0L) return - if (howoften == 1) { + val bukkitRunnable = object : KSpigotRunnable() { - val mergedRunnable: () -> Unit = { - runnable?.invoke(KSpigotRunnable(1)) - endCallback?.invoke() - } + private var curCounter = 0L - if (sync) { - if (delay != null && delay >= 1) - Bukkit.getScheduler().runTaskLater(kSpigot, mergedRunnable, delay) - else - Bukkit.getScheduler().runTask(kSpigot, mergedRunnable) - } else { - if (delay != null && delay >= 1) - Bukkit.getScheduler().runTaskLaterAsynchronously(kSpigot, mergedRunnable, delay) - else - Bukkit.getScheduler().runTaskAsynchronously(kSpigot, mergedRunnable) - } + override fun run() { - } else if (howoften > 1) { + var ranOut = false + if (howOften != null) { - val realPeriod: Long = period ?: 20 - val realDelay: Long = delay ?: 0 + counterDown = howOften - curCounter - val bukkitRunnable = object : BukkitRunnable() { + curCounter++ + if (curCounter >= howOften) + ranOut = true - private val kSpigotRunnable = KSpigotRunnable(howoften, this) - override fun run() { + counterUp = curCounter - runnable?.invoke(kSpigotRunnable) + } - kSpigotRunnable.counter-- + runnable?.invoke(this) - if (kSpigotRunnable.counter >= 0 || (this.isCancelled && safe)) { - - if (!this.isCancelled) - this.cancel() - - endCallback?.let { - it.invoke() - kSpigot.kRunnableHolder.runnableEndCallbacks -= this - } - - return - - } + if (ranOut) cancel() + if (isCancelled) { + if (safe || ranOut) + kRunnableHolder.activate(this) + else + kRunnableHolder.remove(this) } } - if (safe) - if (endCallback != null) - kSpigot.kRunnableHolder.runnableEndCallbacks[bukkitRunnable] = endCallback - - if (sync) - bukkitRunnable.runTaskTimer(kSpigot, realDelay, realPeriod) - else - bukkitRunnable.runTaskTimerAsynchronously(kSpigot, realDelay, realPeriod) - } + if (safe) if (endCallback != null) kRunnableHolder.add(bukkitRunnable, endCallback) + + if (sync) + bukkitRunnable.runTaskTimer(this, delay, period ?: 20) + else + bukkitRunnable.runTaskTimerAsynchronously(this, delay, period ?: 20) + } -fun bukkitSync(kSpigot: KSpigot, runnable: () -> Unit) - = Bukkit.getScheduler().runTask(kSpigot, runnable) +/** + * Starts a synchronous task. + */ +fun Plugin.sync(runnable: () -> Unit) + = Bukkit.getScheduler().runTask(this, runnable) -fun bukkitAsync(kSpigot: KSpigot, runnable: () -> Unit) - = Bukkit.getScheduler().runTaskAsynchronously(kSpigot, runnable) \ No newline at end of file +/** + * Starts an asynchronous task. + */ +fun Plugin.async(runnable: () -> Unit) + = Bukkit.getScheduler().runTaskAsynchronously(this, runnable) \ No newline at end of file