Skip to content

Commit

Permalink
Refactoring + scheduling + introduced Task Tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt-MX committed Jan 22, 2024
1 parent 3f6739d commit 0b27f4d
Show file tree
Hide file tree
Showing 25 changed files with 287 additions and 45 deletions.
9 changes: 5 additions & 4 deletions api/src/main/kotlin/com/mattmx/ktgui/GuiManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.mattmx.ktgui
import com.mattmx.ktgui.components.screen.IGuiScreen
import com.mattmx.ktgui.configuration.Configuration
import com.mattmx.ktgui.extensions.getOpenGui
import jdk.jfr.Experimental
import com.mattmx.ktgui.scheduling.Scheduling
import com.mattmx.ktgui.scheduling.TaskTracker
import com.mattmx.ktgui.scheduling.TaskTrackerTask
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
Expand All @@ -16,8 +18,6 @@ import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.event.server.PluginDisableEvent
import org.bukkit.plugin.java.JavaPlugin
import org.jetbrains.annotations.ApiStatus
import java.io.ObjectInputFilter.Config
import java.util.*

/**
* Handles all GUI click events, as well
Expand All @@ -30,10 +30,11 @@ object GuiManager : Listener {
private val configurations = hashMapOf<JavaPlugin, Configuration>()
lateinit var owningPlugin: JavaPlugin

fun init(plugin: JavaPlugin) : Boolean {
fun init(plugin: JavaPlugin): Boolean {
if (initialized) return false
initialized = true
owningPlugin = plugin
Scheduling.plugin = plugin
Bukkit.getPluginManager().registerEvents(this, plugin)
return true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mattmx.ktgui.commands

import com.mattmx.ktgui.utils.not
import com.mattmx.ktgui.scheduling.not
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mattmx.ktgui.commands

import com.mattmx.ktgui.utils.not
import com.mattmx.ktgui.scheduling.not
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.mattmx.ktgui.components.signal.GuiSignalOwner
import com.mattmx.ktgui.event.PreGuiBuildEvent
import com.mattmx.ktgui.event.PreGuiOpenEvent
import com.mattmx.ktgui.extensions.setOpenGui
import com.mattmx.ktgui.utils.isAsync
import com.mattmx.ktgui.scheduling.isAsync
import com.mattmx.ktgui.utils.legacy
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.mattmx.ktgui.event

import com.mattmx.ktgui.components.screen.IGuiScreen
import com.mattmx.ktgui.utils.isAsync
import com.mattmx.ktgui.scheduling.isAsync
import org.bukkit.entity.Player
import org.bukkit.event.Cancellable
import org.bukkit.event.Event
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.mattmx.ktgui.event

import com.mattmx.ktgui.components.screen.IGuiScreen
import com.mattmx.ktgui.utils.isAsync
import com.mattmx.ktgui.scheduling.isAsync
import org.bukkit.entity.Player
import org.bukkit.event.Cancellable
import org.bukkit.event.Event
Expand Down
66 changes: 66 additions & 0 deletions api/src/main/kotlin/com/mattmx/ktgui/scheduling/TaskTracker.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.mattmx.ktgui.scheduling

import org.bukkit.scheduler.BukkitTask
import java.util.*

class TaskTracker {
private val list = Collections.synchronizedList(arrayListOf<BukkitTask>())

fun runAsync(block: TaskTrackerTask.() -> Unit) {
var task: TaskTrackerTask? = null
task = TaskTrackerTask(this, async {
block(task!!)
list.remove(this)
}.apply { list.add(this) })
}

fun runSync(block: TaskTrackerTask.() -> Unit) {
var task: TaskTrackerTask? = null
task = TaskTrackerTask(this, sync {
block(task!!)
list.remove(this)
}.apply { list.add(this) })
}

fun runAsyncLater(period: Long, block: TaskTrackerTask.() -> Unit) {
var task: TaskTrackerTask? = null
task = TaskTrackerTask(this, asyncDelayed(period) {
block(task!!)
list.remove(this)
}.apply { list.add(this) })
}

fun runSyncLater(period: Long, block: TaskTrackerTask.() -> Unit) {
var task: TaskTrackerTask? = null
task = TaskTrackerTask(this, syncDelayed(period) {
block(task!!)
list.remove(this)
}.apply { list.add(this) })
}

fun runAsyncRepeat(delay: Long, period: Long = 0L, block: TaskTrackerTask.() -> Unit) {
var task: TaskTrackerTask? = null
task = TaskTrackerTask(this, asyncRepeat(delay, period) {
block(task!!)
task!!.iterations++
}.apply { list.add(this) })
}

fun runSyncRepeat(delay: Long, period: Long = 0L, block: TaskTrackerTask.() -> Unit) {
var task: TaskTrackerTask? = null
task = TaskTrackerTask(this, syncRepeat(delay, period) {
block(task!!)
task!!.iterations++
}.apply { list.add(this) })
}

fun cancelAll() = list.apply {
forEach { it.cancel() }
list.clear()
}

fun removeTask(task: BukkitTask) {
list.remove(task)
}

}
15 changes: 15 additions & 0 deletions api/src/main/kotlin/com/mattmx/ktgui/scheduling/TaskTrackerTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mattmx.ktgui.scheduling

import org.bukkit.scheduler.BukkitTask

class TaskTrackerTask(
private val owner: TaskTracker,
private val task: BukkitTask
) {
var iterations = 0

fun cancel() {
owner.removeTask(task)
task.cancel()
}
}
181 changes: 181 additions & 0 deletions api/src/main/kotlin/com/mattmx/ktgui/scheduling/scheduling.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package com.mattmx.ktgui.scheduling

import org.bukkit.Bukkit
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
}

/**
* Forces code to run in an async context.
*
* @param block to run
*/
fun forceAsync(block: () -> Unit) {
if (!isAsync()) async { block() }
else block()
}

/**
* Forces code to run on the main thread.
*
* @param block to run
*/
fun forceMainThread(block: () -> Unit) {
if (isAsync()) sync { block() }
else block()
}

/**
* Returns true if the context of the code is async.
*
* @return if code is running async
*/
fun isAsync() = !Bukkit.isPrimaryThread()

/**
* 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): BukkitTask {
var delayedInit: BukkitTask? = null
delayedInit = Bukkit.getScheduler().runTask(Scheduling.plugin) { -> task(delayedInit!!) }
return delayedInit
}

/**
* 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, task: BukkitTask.() -> Unit): BukkitTask {
var delayedInit: BukkitTask? = null
delayedInit = Bukkit.getScheduler().runTaskTimer(Scheduling.plugin, {-> task(delayedInit!!) }, delay, period)
return delayedInit
}

/**
* 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): BukkitTask {
var delayedInit: BukkitTask? = null
delayedInit = Bukkit.getScheduler().runTaskLater(Scheduling.plugin, {-> task(delayedInit!!) }, delay)
return delayedInit
}

/**
* Schedule an async function to run next tick.
*
* @author MattMX
* @param task to execute asynchronously
*/
fun async(task: BukkitTask.() -> Unit): BukkitTask {
var delayedInit: BukkitTask? = null
delayedInit = Bukkit.getScheduler().runTaskAsynchronously(Scheduling.plugin) { -> task(delayedInit!!) }
return delayedInit
}

/**
* 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, task: BukkitTask.() -> Unit): BukkitTask {
var delayedInit: BukkitTask? = null
delayedInit = Bukkit.getScheduler().runTaskTimerAsynchronously(Scheduling.plugin, {-> task(delayedInit!!) }, delay, period)
return delayedInit
}

/**
* 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): BukkitTask {
var delayedInit: BukkitTask? = null
delayedInit = Bukkit.getScheduler().runTaskLaterAsynchronously(Scheduling.plugin, {-> task(delayedInit!!) }, delay)
return delayedInit
}

/**
* 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
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.mattmx.ktgui.scoreboards

import com.mattmx.ktgui.utils.legacy
import com.mattmx.ktgui.utils.legacyColor
import com.mattmx.ktgui.utils.not
import com.mattmx.ktgui.scheduling.not
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.OfflinePlayer
import org.bukkit.entity.Player
import org.bukkit.scoreboard.Criteria
import org.bukkit.scoreboard.DisplaySlot
Expand Down
5 changes: 0 additions & 5 deletions api/src/main/kotlin/com/mattmx/ktgui/utils/scheduling.kt

This file was deleted.

9 changes: 1 addition & 8 deletions plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
package com.mattmx.ktgui

import com.mattmx.ktgui.commands.simpleCommand
import com.mattmx.ktgui.dsl.event
import com.mattmx.ktgui.examples.*
import com.mattmx.ktgui.utils.not
import com.mattmx.ktgui.scheduling.not
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.block.Block
import org.bukkit.entity.FallingBlock
import org.bukkit.event.entity.EntityChangeBlockEvent
import org.bukkit.persistence.PersistentDataType
import org.bukkit.plugin.java.JavaPlugin
import java.util.logging.Logger

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.mattmx.ktgui.KotlinGui
import com.mattmx.ktgui.extensions.removeScoreboard
import com.mattmx.ktgui.extensions.stripColor
import com.mattmx.ktgui.scoreboards.scoreboard
import com.mattmx.ktgui.utils.not
import com.mattmx.ktgui.scheduling.not
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import java.lang.Integer.min
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.mattmx.ktgui.KotlinGui
import com.mattmx.ktgui.components.screen.GuiScreen
import com.mattmx.ktgui.dsl.button
import com.mattmx.ktgui.dsl.gui
import com.mattmx.ktgui.utils.not
import com.mattmx.ktgui.scheduling.not
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryType
Expand Down
Loading

0 comments on commit 0b27f4d

Please sign in to comment.