Scoreboard sidebar now supports Component (with RGB and stuff) + little improvement of Chat API
This commit is contained in:
parent
ea1cf90119
commit
9391dcafbc
@ -268,16 +268,7 @@ public class ChatColorUtil {
|
||||
|
||||
|
||||
public static class ChatValueGradient {
|
||||
//private record GradientValueColor(float value, ChatColor color) { } // Java 16
|
||||
private static class GradientValueColor {
|
||||
private final float value;
|
||||
private final TextColor color;
|
||||
public GradientValueColor(float value, TextColor color) {
|
||||
this.value = value; this.color = color;
|
||||
}
|
||||
public float value() { return value; }
|
||||
public TextColor color() { return color; }
|
||||
}
|
||||
private record GradientValueColor(float value, TextColor color) { } // Java 16
|
||||
|
||||
List<GradientValueColor> colors = new ArrayList<>();
|
||||
|
||||
|
@ -5,6 +5,7 @@ import java.util.Objects;
|
||||
import fr.pandacube.lib.core.chat.Chat.FormatableChat;
|
||||
import fr.pandacube.lib.core.util.Log;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
@ -77,13 +78,14 @@ public abstract class ChatStatic {
|
||||
}
|
||||
|
||||
public static FormatableChat playerNameText(String legacyText) {
|
||||
return legacyText(legacyText).white();
|
||||
FormatableChat fc = legacyText(legacyText);
|
||||
fc.builder.colorIfAbsent(NamedTextColor.WHITE);
|
||||
return fc;
|
||||
}
|
||||
|
||||
public static FormatableChat playerNameComponent(Component c) {
|
||||
FormatableChat fc = chatComponent(c);
|
||||
if (c.color() == null)
|
||||
fc.white();
|
||||
fc.builder.colorIfAbsent(NamedTextColor.WHITE);
|
||||
return fc;
|
||||
}
|
||||
|
||||
|
@ -1,129 +0,0 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
|
||||
import fr.pandacube.lib.core.chat.Chat;
|
||||
import fr.pandacube.lib.core.chat.ChatUtil;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
public class ScoreBoardUtil {
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
* @implNote The implementation makes sure that the minimum amount of data is transmitted to the client,
|
||||
* to reduce bandwith usage and avoid the sidebar flickering.
|
||||
* <ul>
|
||||
* <li>If a provided line is already present in the sidebar, and at the same line number, it will not be updated.
|
||||
* <li>If a provided line is already present but at another position, only the score (i.e. the line number) is updated.
|
||||
* <li>If a provided line was not present before, it is added as a new score entry in the scoreboard.
|
||||
* <li>If a line that was already present is not in the provided lines, it is removed from the scoreboard.
|
||||
* <li>The title is only updated if it has actually changed.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Chat title, String[] lines) {
|
||||
if (scBrd == null) throw new IllegalArgumentException("scBrd doit être non null");
|
||||
if (lines == null) lines = new String[0];
|
||||
|
||||
Objective obj = scBrd.getObjective("sidebar_autogen");
|
||||
if (obj != null && !obj.getCriteria().equalsIgnoreCase("dummy")) {
|
||||
// objective present but with wrong criteria, removing it
|
||||
obj.unregister();
|
||||
obj = null;
|
||||
}
|
||||
|
||||
|
||||
if (obj == null) {
|
||||
obj = scBrd.registerNewObjective("sidebar_autogen", "dummy", title.getAdv());
|
||||
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
}
|
||||
else {
|
||||
// only update title if needed
|
||||
if (!title.getAdv().equals(obj.displayName()))
|
||||
obj.displayName(title.getAdv());
|
||||
// fix display slot if someone else changed it
|
||||
if (DisplaySlot.SIDEBAR != obj.getDisplaySlot())
|
||||
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
}
|
||||
|
||||
|
||||
filterLines(lines);
|
||||
|
||||
List<String> listLines = Arrays.asList(lines);
|
||||
|
||||
// remove lines from the scoreboard that are not in the provided array
|
||||
Objective fObj = obj;
|
||||
scBrd.getEntries().stream()
|
||||
.filter(e -> !listLines.contains(e))
|
||||
.filter(e -> fObj.getScore(e).isScoreSet())
|
||||
.forEach(scBrd::resetScores);
|
||||
|
||||
// add and update others lines
|
||||
int boardPos = lines.length;
|
||||
for (String line : lines) {
|
||||
Score score = obj.getScore(line);
|
||||
|
||||
if (score.getScore() != boardPos)
|
||||
score.setScore(boardPos);
|
||||
|
||||
boardPos--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
* @implNote The implementation makes sure that the minimum amount of data is transmitted to the client,
|
||||
* to reduce bandwith usage and avoid the sidebar flickering.
|
||||
* <ul>
|
||||
* <li>If a provided line is already present in the sidebar, and at the same line number, it will not be updated.
|
||||
* <li>If a provided line is already present but at another position, only the score (i.e. the line number) is updated.
|
||||
* <li>If a provided line was not present before, it is added as a new score entry in the scoreboard.
|
||||
* <li>If a line that was already present is not in the provided lines, it is removed from the scoreboard.
|
||||
* <li>The title is only updated if it has actually changed.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Chat title, List<String> lines) {
|
||||
updateScoreboardSidebar(scBrd, title, lines.toArray(new String[lines.size()]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static void filterLines(String[] lines) {
|
||||
List<String> previous = new ArrayList<>();
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i] == null ? "" : ChatUtil.truncateAtLengthWithoutReset(lines[i], 40);
|
||||
if (previous.contains(line)) {
|
||||
for (ChatColor c : ChatColor.values()) {
|
||||
line = ChatUtil.truncateAtLengthWithoutReset(lines[i], 38) + c;
|
||||
if (!previous.contains(line)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lines[i] = line;
|
||||
previous.add(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
|
||||
import fr.pandacube.lib.core.chat.Chat;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class ScoreboardUtil {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Component title, Component[] lines) {
|
||||
|
||||
Objective obj = scBrd.getObjective("sidebar_autogen");
|
||||
if (obj != null && !obj.getCriteria().equalsIgnoreCase("dummy")) {
|
||||
// objective present but with wrong criteria, removing it
|
||||
obj.unregister();
|
||||
obj = null;
|
||||
}
|
||||
|
||||
|
||||
if (obj == null) {
|
||||
obj = scBrd.registerNewObjective("sidebar_autogen", "dummy", title);
|
||||
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
}
|
||||
else {
|
||||
// only update title if needed
|
||||
if (!title.equals(obj.displayName())) {
|
||||
obj.displayName(title);
|
||||
}
|
||||
// fix display slot if someone else changed it
|
||||
if (DisplaySlot.SIDEBAR != obj.getDisplaySlot()) {
|
||||
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
}
|
||||
}
|
||||
|
||||
ChatColor[] colors = ChatColor.values();
|
||||
|
||||
/*
|
||||
* Scanning lines from last to first, keeping only the 15 first lines
|
||||
*/
|
||||
int score = 1, i = 0;
|
||||
for (int lineIndex = Math.min(lines.length, 15) - 1; lineIndex >= 0; i++, score++, lineIndex--) {
|
||||
String teamId = "sidebar_team" + score;
|
||||
String sbEntry = colors[i].toString();
|
||||
Team tLine = scBrd.getTeam(teamId);
|
||||
if (tLine == null) {
|
||||
tLine = scBrd.registerNewTeam(teamId);
|
||||
}
|
||||
if (!tLine.hasEntry(sbEntry)) {
|
||||
tLine.addEntry(sbEntry);
|
||||
}
|
||||
|
||||
if (!tLine.prefix().equals(lines[lineIndex])) {
|
||||
tLine.prefix(lines[lineIndex]);
|
||||
}
|
||||
|
||||
Score scoreEntry = obj.getScore(sbEntry);
|
||||
if (scoreEntry.getScore() != score) {
|
||||
scoreEntry.setScore(score);
|
||||
}
|
||||
}
|
||||
|
||||
// clean older data when we are reducing the number of line displayed
|
||||
for (; i < colors.length; i++, score++) {
|
||||
String teamId = "sidebar_team" + score;
|
||||
String sbEntry = colors[i].toString();
|
||||
|
||||
if (obj.getScore(sbEntry).isScoreSet()) {
|
||||
scBrd.resetScores(sbEntry);
|
||||
}
|
||||
|
||||
Team tLine = scBrd.getTeam(teamId);
|
||||
if (tLine != null && !tLine.prefix().equals(Component.empty())) {
|
||||
tLine.prefix(Component.empty());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Chat title, Chat[] lines) {
|
||||
Component[] cmpLines = new Component[lines.length];
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
cmpLines[i] = lines[i].getAdv();
|
||||
}
|
||||
updateScoreboardSidebar(scBrd, title.getAdv(), cmpLines);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the sidebar of the provided scoreboard, with the given title and lines.
|
||||
*
|
||||
* @param scBrd the scoreboard
|
||||
* @param title the title of the sidebar
|
||||
* @param lines the lines that have to be displayed. Null values are treated as empty lines.
|
||||
* The lines support legacy formatting only, and will be truncated to 40 characters.
|
||||
* Lines present multiple times will have hidden characters appended to make them different.
|
||||
* Vanilla Java Edition clients only display the 15 first lines.
|
||||
*/
|
||||
public static void updateScoreboardSidebar(Scoreboard scBrd, Chat title, List<Chat> lines) {
|
||||
Component[] cmpLines = new Component[lines.size()];
|
||||
for (int i = 0; i < cmpLines.length; i++) {
|
||||
cmpLines[i] = lines.get(i).getAdv();
|
||||
}
|
||||
updateScoreboardSidebar(scBrd, title.getAdv(), cmpLines);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user