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 {
|
public static class ChatValueGradient {
|
||||||
//private record GradientValueColor(float value, ChatColor color) { } // Java 16
|
private record GradientValueColor(float value, TextColor 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; }
|
|
||||||
}
|
|
||||||
|
|
||||||
List<GradientValueColor> colors = new ArrayList<>();
|
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.chat.Chat.FormatableChat;
|
||||||
import fr.pandacube.lib.core.util.Log;
|
import fr.pandacube.lib.core.util.Log;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
|
||||||
@ -77,13 +78,14 @@ public abstract class ChatStatic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static FormatableChat playerNameText(String legacyText) {
|
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) {
|
public static FormatableChat playerNameComponent(Component c) {
|
||||||
FormatableChat fc = chatComponent(c);
|
FormatableChat fc = chatComponent(c);
|
||||||
if (c.color() == null)
|
fc.builder.colorIfAbsent(NamedTextColor.WHITE);
|
||||||
fc.white();
|
|
||||||
return fc;
|
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