From 947289bc2679566f3fee53e747e999caa00ebc4f Mon Sep 17 00:00:00 2001 From: MattMX Date: Thu, 4 Jul 2024 22:43:16 +0100 Subject: [PATCH] Dynamic scoreboard, part of #34 Syntax/structure not final. --- .../ktgui/scoreboards/ComponentSupplier.kt | 11 ++++ .../scoreboards/DynamicScoreboardBuilder.kt | 54 +++++++++++++++++++ .../ktgui/scoreboards/ScoreboardBuilder.kt | 3 +- .../ScoreboardComponentSupplier.kt | 11 ++++ .../main/kotlin/com/mattmx/ktgui/KotlinGui.kt | 4 +- .../ktgui/examples/SignalScoreboardExample.kt | 46 ++++++++++++++-- 6 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ComponentSupplier.kt create mode 100644 api/src/main/kotlin/com/mattmx/ktgui/scoreboards/DynamicScoreboardBuilder.kt create mode 100644 api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardComponentSupplier.kt diff --git a/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ComponentSupplier.kt b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ComponentSupplier.kt new file mode 100644 index 0000000..e1c1101 --- /dev/null +++ b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ComponentSupplier.kt @@ -0,0 +1,11 @@ +package com.mattmx.ktgui.scoreboards + +import net.kyori.adventure.text.Component + +open class ComponentSupplier( + val supplier: () -> Component +) { + + operator fun invoke() = supplier() + +} \ No newline at end of file diff --git a/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/DynamicScoreboardBuilder.kt b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/DynamicScoreboardBuilder.kt new file mode 100644 index 0000000..a5fbfe5 --- /dev/null +++ b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/DynamicScoreboardBuilder.kt @@ -0,0 +1,54 @@ +package com.mattmx.ktgui.scoreboards + +import com.mattmx.ktgui.scheduling.TaskTracker +import net.kyori.adventure.text.Component + +open class DynamicScoreboardBuilder( + title: Component = Component.empty() +) : ScoreboardBuilder(title) { + private val tasks = TaskTracker() + + open infix fun title(supplier: () -> Component) = + title(ScoreboardComponentSupplier(supplier)) + + open infix fun title(supplier: ScoreboardComponentSupplier) = supplier.apply { + val initialComponent = supplier() + isTitleComponent = true + title = initialComponent + } + + operator fun ScoreboardComponentSupplier.unaryPlus() = apply { add(this) } + + operator fun (() -> Component).unaryPlus() = + ScoreboardComponentSupplier(this).apply { add(this) } + + infix fun add(supplier: ScoreboardComponentSupplier) { + val initialComponent = supplier() + val index = add(initialComponent) + supplier.indexes.add(index) + } + + infix fun scoreboardLine(block: () -> Component) = + ScoreboardComponentSupplier(block) + + infix fun ScoreboardComponentSupplier.updateEvery(ticks: Long) = apply { + tasks.runAsyncRepeat(ticks) { + val component = invoke() + if (isTitleComponent) { + title = component + } + indexes.forEach { set(it, component) } + } + } + + override fun clear() { + super.clear() + tasks.cancelAll() + } +} + +fun dynamicScoreboard(title: Component, block: DynamicScoreboardBuilder.() -> Unit) = + DynamicScoreboardBuilder(title).apply(block) + +fun dynamicScoreboard(block: DynamicScoreboardBuilder.() -> Unit) = + DynamicScoreboardBuilder().apply(block) \ No newline at end of file diff --git a/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardBuilder.kt b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardBuilder.kt index 1eecdc5..52723bd 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardBuilder.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardBuilder.kt @@ -19,6 +19,7 @@ open class ScoreboardBuilder( ) { var title: Component = title set(value) { + objective.setAutoUpdateDisplay(true) this.objective.displayName(title) field = value } @@ -102,7 +103,7 @@ open class ScoreboardBuilder( /** * Clears all scoreboard content */ - fun clear() { + open fun clear() { scoreboardLines.clear() scoreboard.resetScores(name) } diff --git a/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardComponentSupplier.kt b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardComponentSupplier.kt new file mode 100644 index 0000000..0cf548a --- /dev/null +++ b/api/src/main/kotlin/com/mattmx/ktgui/scoreboards/ScoreboardComponentSupplier.kt @@ -0,0 +1,11 @@ +package com.mattmx.ktgui.scoreboards + +import net.kyori.adventure.text.Component +import java.util.* + +class ScoreboardComponentSupplier( + supplier: () -> Component +) : ComponentSupplier(supplier) { + val indexes = arrayListOf() + var isTitleComponent: Boolean = false +} \ No newline at end of file diff --git a/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt b/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt index edefdce..8be3e2d 100644 --- a/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt +++ b/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt @@ -45,6 +45,7 @@ class KotlinGui : JavaPlugin() { val animatedScoreboard = AnimatedScoreboardExample() val scoreboardExample = ScoreboardExample() + val signalScoreboardExample = SignalScoreboardExample() val examples = hashMapOf( "animated-scoreboard" to { animatedScoreboard }, "scoreboard" to { scoreboardExample }, @@ -62,7 +63,8 @@ class KotlinGui : JavaPlugin() { "java-simple" to { JavaGuiExample() }, "java-new" to { JavaUpdateExample() }, "refresh" to { RefreshBlockExample() }, - "config-gui" to { GuiConfigExample() } + "config-gui" to { GuiConfigExample() }, + "refresh-scoreboard" to { signalScoreboardExample } ) GuiHookExample.registerListener(this) diff --git a/plugin/src/main/kotlin/com/mattmx/ktgui/examples/SignalScoreboardExample.kt b/plugin/src/main/kotlin/com/mattmx/ktgui/examples/SignalScoreboardExample.kt index cf86146..b6095fb 100644 --- a/plugin/src/main/kotlin/com/mattmx/ktgui/examples/SignalScoreboardExample.kt +++ b/plugin/src/main/kotlin/com/mattmx/ktgui/examples/SignalScoreboardExample.kt @@ -1,17 +1,53 @@ package com.mattmx.ktgui.examples -import com.mattmx.ktgui.scoreboards.scoreboard +import com.mattmx.ktgui.scoreboards.dynamicScoreboard import com.mattmx.ktgui.utils.not +import com.mattmx.ktgui.utils.placeholders +import com.mattmx.ktgui.utils.pretty +import com.mattmx.ktgui.utils.seconds import net.kyori.adventure.text.Component +import org.bukkit.entity.Player import java.text.DateFormat import java.util.* +import kotlin.math.max +import kotlin.math.min -class SignalScoreboardExample { +class SignalScoreboardExample : Example { - val board = scoreboard(!"&fSignals x Scoreboard") { - +!"&fFirst line" + val board = dynamicScoreboard(!"D7068&lYour Server") { + + val le = 40 + var i = 0 + val line = scoreboardLine { + i = if (i > le) 0 else i + 1 + + val l = max(0, i - 1) + val r = min(le, le - i + 1) + + !" D7068&m${" ".repeat(l)}+C59E&m D7068&m${" ".repeat(r)}" + } updateEvery 5L + + +line + +!" DFAFFLobby" +Component.empty() - +!"&f${DateFormat.getTimeInstance().format(Date())}" + + +{ !" DFAFF$ &f${(0..1_000_000_000_000).random().pretty()}" } updateEvery 1.5.seconds + +{ !" DFAFF\uD83D\uDD25 &f%server_online%".placeholders(null) } updateEvery 5.seconds + +{ !" DFAFF⌛ &f${DateFormat.getTimeInstance().format(Date())}" } updateEvery 1.seconds + +Component.empty() + +line + } + + override fun run(player: Player) { + val shown = board.isShownFor(player) + + if (shown) { + board.removeFor(player) + player.sendMessage(!"&fHiding scoreboard") + } else { + player.sendMessage(!"&fShowing scoreboard") + board.showFor(player) + } } } \ No newline at end of file