package cc.maxmc.blastingcrisis.game import cc.maxmc.blastingcrisis.configuration.GlobalSettings import cc.maxmc.blastingcrisis.misc.pluginScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import taboolib.common.platform.function.adaptCommandSender import taboolib.module.lang.getLocaleFile import taboolib.platform.util.sendLang import kotlin.time.Duration import kotlin.time.DurationUnit import kotlin.time.toDuration class GameTimer(private val game: Game) { private val events = ArrayList Unit>>() private lateinit var timerJob: Job private lateinit var countdownJob: Job private var start: Long = 0 var current = GlobalSettings.timeToStart lateinit var nextEvent: Triple Unit> private set fun beginCountdown() { countdownJob = pluginScope.launch { while (current > 0) { if (!isActive) { return@launch } countdown() current-- delay(1000) } game.start() } } private fun countdown() { game.scoreboard.sendScoreboard() game.broadcast { val locale = adaptCommandSender(it).getLocaleFile()!! if (locale.nodes.containsKey("game_countdown_${current}")) { it.sendLang("game_countdown_${current}") } } } fun resetCountdown() { game.broadcast { it.sendLang("time_reset") } current = GlobalSettings.timeToStart } fun startTimer() { start = System.nanoTime() timerJob = pluginScope.launch { while (true) { val toDos = events.filter { it.first <= System.nanoTime() } toDos.forEach { (_, _, toDo) -> toDo() } events.removeAll(toDos.toSet()) events.minByOrNull { it.first }?.also { val duration = (it.first - System.nanoTime()).toDuration(DurationUnit.NANOSECONDS) nextEvent = Triple(duration, it.second, it.third) } ?: let { nextEvent = Triple(Duration.INFINITE, "end") {} } game.scoreboard.sendScoreboard() delay(1000) } } } fun submitEvent(name: String, time: java.time.Duration, `do`: () -> Unit) { events.add(Triple(time.toNanos() + start, name, `do`)) } }