Author SHA1 Message Date
NotAlexNoyle c486ce864b Refactor sidebar to example-style layout 2025-12-10 06:19:08 -05:00
NotAlexNoyle 1024ab2c9f Merge pull request #4 from true-og/codex/revise-plugin-to-match-api-example
Refactor scoreboard to component sidebar layout
2025-12-10 06:12:36 -05:00
NotAlexNoyle 516fb5a2ea Refactor scoreboard to component sidebar layout 2025-12-10 06:12:14 -05:00
NotAlexNoyle 80f6d3c8bf Merge pull request #3 from true-og/codex/revise-plugin-to-import-scoreboard-library
Update Scoreboard Library dependencies for multi-version support
2025-12-10 05:54:31 -05:00
NotAlexNoyle 465f9d0a3e Update scoreboard library imports 2025-12-10 05:54:04 -05:00
NotAlexNoyle 8baa4797cd Merge pull request #1 from true-og/codex/update-scoreboard-display-to-use-scoreboard-library
Switch to scoreboard-library
2025-12-10 05:39:51 -05:00
NotAlexNoyle bcbea6036b Switch to scoreboard-library 2025-12-10 05:36:25 -05:00
2 changed files with 170 additions and 41 deletions

No files matched your search

+9 -1
View File
@@ -34,6 +34,8 @@ version = "1.0" // Declare plugin version (will be in .jar).
val apiVersion = "1.19" // Declare minecraft server target version.
val scoreboardLibraryVersion = "2.1.0" // Declare Scoreboard Library version.
/* ----------------------------- Resources ----------------------------- */
tasks.named<ProcessResources>("processResources") {
val props = mapOf("version" to version, "apiVersion" to apiVersion)
@@ -48,6 +50,7 @@ repositories {
gradlePluginPortal() // Import the Gradle Plugin Portal Maven Repository.
maven { url = uri("https://repo.purpurmc.org/snapshots") } // Import the PurpurMC Maven Repository.
maven { url = uri("https://repo.hotten.cloud/snapshots") } // Import the ScoreboardLib library.
maven { url = uri("https://jitpack.io") } // Import the MegavexNetwork scoreboard-library.
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let { // TrueOG Bootstrap mavenLocal().
val dir = file(it)
@@ -70,7 +73,12 @@ dependencies {
compileOnlyApi(project(":libs:DiamondBank-OG")) {
attributes { attribute(kotlinAttribute, true) }
} // Import TrueOG network DiamondBank-OG Kotlin API (from source).
implementation("me.tigerhix.lib:scoreboard:1.0.1-SNAPSHOT")
implementation("net.megavex:scoreboard-library-api:$scoreboardLibraryVersion")
runtimeOnly("net.megavex:scoreboard-library-implementation:$scoreboardLibraryVersion")
runtimeOnly("net.megavex:scoreboard-library-modern:$scoreboardLibraryVersion")
runtimeOnly("net.megavex:scoreboard-library-packetevents:$scoreboardLibraryVersion")
runtimeOnly("net.megavex:scoreboard-library-legacy:$scoreboardLibraryVersion")
implementation("net.kyori:adventure-platform-bukkit:4.3.4")
}
apply(from = "eclipse.gradle.kts") // Import eclipse classpath support script.
+161 -40
View File
@@ -3,6 +3,7 @@
package plugin;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -12,12 +13,17 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import me.tigerhix.lib.scoreboard.ScoreboardLib;
import me.tigerhix.lib.scoreboard.common.EntryBuilder;
import me.tigerhix.lib.scoreboard.type.Entry;
import me.tigerhix.lib.scoreboard.type.Scoreboard;
import me.tigerhix.lib.scoreboard.type.ScoreboardHandler;
import net.megavex.scoreboardlibrary.api.ScoreboardLibrary;
import net.megavex.scoreboardlibrary.api.sidebar.Sidebar;
import net.megavex.scoreboardlibrary.api.sidebar.SidebarManager;
import net.megavex.scoreboardlibrary.api.sidebar.animation.CollectionSidebarAnimation;
import net.megavex.scoreboardlibrary.api.sidebar.animation.SidebarAnimation;
import net.megavex.scoreboardlibrary.api.sidebar.component.ComponentSidebarLayout;
import net.megavex.scoreboardlibrary.api.sidebar.component.SidebarComponent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.model.user.User;
@@ -28,10 +34,17 @@ public class ScoreboardOG extends JavaPlugin {
private static ScoreboardOG instance;
private FileConfiguration config;
private final Map<UUID, Scoreboard> boards = new HashMap<>();
private final Map<UUID, PlayerSidebar> boards = new HashMap<>();
private final Map<UUID, BukkitTask> updateTasks = new HashMap<>();
private ScoreboardLibrary scoreboardLibrary;
private SidebarManager sidebarManager;
private LuckPerms luckPerms;
private final LegacyComponentSerializer legacySerializer = LegacyComponentSerializer.legacyAmpersand();
public static ScoreboardOG getInstance() {
return instance;
@@ -50,7 +63,9 @@ public class ScoreboardOG extends JavaPlugin {
saveDefaultConfig();
this.config = getConfig();
ScoreboardLib.setPluginInstance(this);
scoreboardLibrary = ScoreboardLibrary.loadNative(this);
sidebarManager = scoreboardLibrary.createSidebarManager();
// Hook LuckPerms API.
final RegisteredServiceProvider<LuckPerms> provider = Bukkit.getServicesManager()
@@ -73,9 +88,24 @@ public class ScoreboardOG extends JavaPlugin {
@Override
public void onDisable() {
boards.values().forEach(Scoreboard::deactivate);
boards.values().forEach(PlayerSidebar::close);
boards.clear();
updateTasks.values().forEach(BukkitTask::cancel);
updateTasks.clear();
if (sidebarManager != null) {
sidebarManager.close();
}
if (scoreboardLibrary != null) {
scoreboardLibrary.close();
}
}
public FileConfiguration config() {
@@ -86,53 +116,104 @@ public class ScoreboardOG extends JavaPlugin {
public void openBoard(Player player) {
final Scoreboard board = ScoreboardLib.createScoreboard(player).setHandler(new ScoreboardHandler() {
final PlayerSidebar playerSidebar = createSidebar(player);
@Override
public String getTitle(Player p) {
playerSidebar.apply();
return "&4♥ &a&lTrue&c&lOG&r&e Network &4♥";
final UUID uuid = player.getUniqueId();
boards.put(uuid, playerSidebar);
final BukkitTask task = Bukkit.getScheduler().runTaskTimer(this, () -> {
if (!player.isOnline()) {
closeBoard(player);
return;
}
@Override
public java.util.List<Entry> getEntries(Player p) {
playerSidebar.tick();
// Fetch LuckPerms prefix with formatting.
String lpPrefix = getLuckPermsPrefixLegacy(p);
lpPrefix = stripLeadingReset(stripTrailingReset(lpPrefix));
}, 10L, 10L);
// Bleed formatting from prefix into name.
final String youTail = joinSpace(lpPrefix, p.getName());
final String youLine = "&aYou:&r " + youTail + "&r";
// Independently formatted Union tag.
final String unionTag = expandMM(p, "<placeholderapi_player:%simpleclans_clan_color_tag%>");
final String unionLine = "&cUnion: &r" + unionTag + "&r";
return new EntryBuilder().next("&c&m----&6&m----&e&m----&2&m----&9&m----&5&m----").next(youLine).blank()
.next("&bDiamonds: " + expandMM(p, "<diamondbankog_balance>")).blank().next(unionLine).blank()
.next("&2Kills: " + expandMM(p, "<placeholderapi_player:%statistic_player_kills%>")).blank()
.next("&4Deaths: " + expandMM(p, "<placeholderapi_player:%statistic_deaths%>")).blank()
.next("&4&m--&0&m--&4> &etrue-og.net &4<&0&m--&4&m--").build();
}
}).setUpdateInterval(10L);
board.activate();
boards.put(player.getUniqueId(), board);
updateTasks.put(uuid, task);
}
public void closeBoard(Player player) {
final Scoreboard board = boards.remove(player.getUniqueId());
if (board != null) {
final PlayerSidebar board = boards.remove(player.getUniqueId());
final BukkitTask task = updateTasks.remove(player.getUniqueId());
board.deactivate();
if (task != null) {
task.cancel();
}
if (board != null) {
board.close();
}
}
private PlayerSidebar createSidebar(Player player) {
final SidebarAnimation<Component> titleAnimation = createTitleAnimation();
final SidebarComponent titleComponent = SidebarComponent.animatedLine(titleAnimation);
final SidebarComponent lines = SidebarComponent.builder()
.addStaticLine(deserialize("&c&m----&6&m----&e&m----&2&m----&9&m----&5&m----"))
.addDynamicLine(() -> deserialize(buildYouLine(player)))
.addBlankLine()
.addDynamicLine(() -> deserialize("&bDiamonds: " + expandMM(player, "<diamondbankog_balance>")))
.addBlankLine()
.addDynamicLine(() -> deserialize(buildUnionLine(player)))
.addBlankLine()
.addDynamicLine(
() -> deserialize("&2Kills: " + expandMM(player, "<placeholderapi_player:%statistic_player_kills%>")))
.addBlankLine()
.addDynamicLine(
() -> deserialize("&4Deaths: " + expandMM(player, "<placeholderapi_player:%statistic_deaths%>")))
.addBlankLine()
.addStaticLine(deserialize("&4&m--&0&m--&4> &etrue-og.net &4<&0&m--&4&m--"))
.build();
return new PlayerSidebar(player, sidebarManager.createSidebar(), new ComponentSidebarLayout(titleComponent, lines),
titleAnimation);
}
private SidebarAnimation<Component> createTitleAnimation() {
return new CollectionSidebarAnimation<>(List.of(deserialize("&4♥ &a&lTrue&c&lOG&r&e Network &4♥")));
}
private String buildYouLine(Player player) {
String lpPrefix = getLuckPermsPrefixLegacy(player);
lpPrefix = stripLeadingReset(stripTrailingReset(lpPrefix));
// Bleed formatting from prefix into name.
final String youTail = joinSpace(lpPrefix, player.getName());
return "&aYou:&r " + youTail + "&r";
}
private String buildUnionLine(Player player) {
final String unionTag = expandMM(player, "<placeholderapi_player:%simpleclans_clan_color_tag%>");
return "&cUnion: &r" + unionTag + "&r";
}
private Component deserialize(String text) {
return legacySerializer.deserialize(text);
}
// Resolve the player's LuckPerms prefix as legacy color codes with any
@@ -238,4 +319,44 @@ public class ScoreboardOG extends JavaPlugin {
}
}
private static final class PlayerSidebar {
private final Player viewer;
private final Sidebar sidebar;
private final ComponentSidebarLayout componentSidebar;
private final SidebarAnimation<Component> titleAnimation;
private PlayerSidebar(Player viewer, Sidebar sidebar, ComponentSidebarLayout componentSidebar,
SidebarAnimation<Component> titleAnimation) {
this.viewer = viewer;
this.sidebar = sidebar;
this.componentSidebar = componentSidebar;
this.titleAnimation = titleAnimation;
}
private void apply() {
componentSidebar.apply(sidebar);
sidebar.addViewer(viewer);
}
private void tick() {
titleAnimation.nextFrame();
componentSidebar.apply(sidebar);
}
private void close() {
sidebar.removeViewer(viewer);
sidebar.close();
}
}
}