Skip to content

Instantly share code, notes, and snippets.

@Matt-MX
Last active September 4, 2024 23:28
Show Gist options
  • Save Matt-MX/2b37270656cb1f2f11036b2fd3210bcb to your computer and use it in GitHub Desktop.
Save Matt-MX/2b37270656cb1f2f11036b2fd3210bcb to your computer and use it in GitHub Desktop.
Utility file to easily call all task types in your Kotlin Bukkit plugins
package co.pvphub.championship.backend.util
import com.mattmx.ktgui.extensions.color
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.scheduler.BukkitTask
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
/**
* Dummy object to store the plugin instance in, so we don't have to provide it for
* every single method call.
*
* You must initialize this before calling any other methods
*
* @author MattMX
*/
object Scheduling {
lateinit var plugin: JavaPlugin
}
/**
* Schedules a method to run synchronously (blocking) on the main thread.
* This will execute next tick.
*
* @author MattMX
* @param task to execute
*/
fun sync(task: (BukkitTask) -> Unit) {
Bukkit.getScheduler().runTask(Scheduling.plugin, task)
}
/**
* Schedules a repeating task to execute the next tick. You can specify the initial delay, period and
* max iterations. Keep in mind the iteration is not actually accepted in the code block.
*
* @author MattMX
* @param period between each execution
* @param delay initial delay before we start the loop
* @param maxIterations how many times we want to do this before cancelling automatically
* @param task to execute
*/
fun syncRepeat(period: Long, delay: Long = 0, maxIterations: Int? = null, task: (BukkitTask) -> Unit) {
maxIterations?.also { maxIt ->
var current = 0
Bukkit.getScheduler().runTaskTimer(Scheduling.plugin, { it ->
current++
if (current > maxIterations) {
it.cancel()
} else task(it)
}, delay, period)
} ?: run { Bukkit.getScheduler().runTaskTimer(Scheduling.plugin, task, delay, period) }
}
/**
* Schedule a task to run in the future.
*
* @author MattMX
* @param delay the delay of when this will execute, must be +ve (in ticks)
* @param task to execute
*/
fun syncDelayed(delay: Long, task: (BukkitTask) -> Unit) {
Bukkit.getScheduler().runTaskLater(Scheduling.plugin, task, delay)
}
/**
* Schedule an async function to run next tick.
*
* @author MattMX
* @param task to execute asynchronously
*/
fun async(task: (BukkitTask) -> Unit) {
Bukkit.getScheduler().runTaskAsynchronously(Scheduling.plugin, task)
}
/**
* Schedules a repeating task to execute asynchronously the next tick. You can specify the initial delay, period and
* max iterations. Keep in mind the iteration is not actually accepted in the code block.
*
* @author MattMX
* @param period between each execution
* @param delay initial delay before we start the loop
* @param maxIterations how many times we want to do this before cancelling automatically
* @param task to execute
*/
fun asyncRepeat(period: Long, delay: Long = 0, maxIterations: Int? = null, task: (BukkitTask) -> Unit) {
maxIterations?.also { maxIt ->
var current = 0
Bukkit.getScheduler().runTaskTimerAsynchronously(Scheduling.plugin, { it ->
current++
if (current > maxIterations) {
it.cancel()
} else task(it)
}, delay, period)
} ?: run { Bukkit.getScheduler().runTaskTimerAsynchronously(Scheduling.plugin, task, delay, period) }
}
/**
* Schedule a task to run in the future to execute asynchronously.
*
* @author MattMX
* @param delay the delay of when this will execute, must be +ve (in ticks)
* @param task to execute
*/
fun asyncDelayed(delay: Long, task: (BukkitTask) -> Unit) {
Bukkit.getScheduler().runTaskLaterAsynchronously(Scheduling.plugin, task, delay)
}
/**
* Returns a [CompletableFuture] with the type you specify.
* We can use this to get values asynchronously.
*
* @author MattMX
* @param block that returns our value
*/
fun <T> future(block: () -> T) : CompletableFuture<T> {
val future = CompletableFuture<T>()
async {
val result = block()
future.complete(result)
}
return future
}
/**
* Similar to [future], will return a [Future] with the type you want.
* This method is Synchronous.
*
* @author MattMX
* @param block that returns our value
*/
fun <T> call(block: () -> T) : Future<T> {
return Bukkit.getScheduler().callSyncMethod(Scheduling.plugin, block)
}
/**
* Utility function that runs blocking to get a value from a future, with a default
* timeout of 30 seconds.
*
* This is useful if you have a function that returns a [Future], like [future], since we can
* call the function and then [await] it.
*
* @author MattMX
*/
inline val <reified T> Future<T>.await : T
get() {
return this.get(30, TimeUnit.SECONDS)
}
/**
* Smaller notation of the [await] function. This could be confusing since it uses the `!` operator so
* keep that in mind to keep your code readable. Although it does look nicer in my opinion.
*
* !foo() as apposed to foo().await
*
* @author MattMX
*/
inline operator fun <reified T> Future<T>.not() = await
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment