From f4642e22a1d6b1301832ed1b184e07eb39617d72 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Sun, 11 Jul 2021 16:14:47 +0200 Subject: [PATCH] Update everything around chat component + some other improvement --- Core/pom.xml | 5 ++ .../java/fr/pandacube/lib/core/chat/Chat.java | 32 ++++--- .../fr/pandacube/lib/core/chat/ChatUtil.java | 73 ++++++++------- .../lib/core/players/IOnlinePlayer.java | 88 ++++++++++++++++++- .../lib/core/players/IPlayerManager.java | 52 ++++++++--- Paper/pom.xml | 4 + .../lib/paper/util/ItemStackBuilder.java | 48 ++++++++-- 7 files changed, 228 insertions(+), 74 deletions(-) diff --git a/Core/pom.xml b/Core/pom.xml index 6a5becc..27b1d5c 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -39,6 +39,11 @@ adventure-platform-bungeecord 4.0.0-SNAPSHOT + + net.kyori + adventure-text-serializer-plain + 4.7.0 + diff --git a/Core/src/main/java/fr/pandacube/lib/core/chat/Chat.java b/Core/src/main/java/fr/pandacube/lib/core/chat/Chat.java index e3c13a8..ac9eb43 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/chat/Chat.java +++ b/Core/src/main/java/fr/pandacube/lib/core/chat/Chat.java @@ -20,6 +20,7 @@ import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration.State; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; @@ -28,7 +29,7 @@ public abstract class Chat extends ChatStatic implements HoverEventSource 50) ? (url.substring(0, 48) + "...") : url; - return chat() + return (FormatableChat) chat() .clickURL(url) .color(Chat.getConfig().urlColor) .hover( hover != null ? hover : Chat.text(dispURL) ) - .then(element) - .get(); + .then(element); } @@ -74,20 +73,20 @@ public class ChatUtil { - public static BaseComponent createCommandLink(String text, String commandWithSlash, String hoverText) { + public static FormatableChat createCommandLink(String text, String commandWithSlash, String hoverText) { return createCommandLink(text, commandWithSlash, hoverText == null ? null : legacyText(hoverText)); } - public static BaseComponent createCommandLink(String text, String commandWithSlash, Chat hoverText) { + public static FormatableChat createCommandLink(String text, String commandWithSlash, Chat hoverText) { return createCommandLink(legacyText(text), commandWithSlash, hoverText); } - /* package */ static BaseComponent createCommandLink(Chat d, String commandWithSlash, Chat hoverText) { + /* package */ static FormatableChat createCommandLink(Chat d, String commandWithSlash, Chat hoverText) { FormatableChat c = chat() .clickCommand(commandWithSlash) .color(Chat.getConfig().commandColor); if (hoverText != null) c.hover(hoverText); - return c.then(d).get(); + return (FormatableChat) c.then(d); } @@ -99,20 +98,20 @@ public class ChatUtil { - public static BaseComponent createCommandSuggest(String text, String commandWithSlash, String hoverText) { + public static FormatableChat createCommandSuggest(String text, String commandWithSlash, String hoverText) { return createCommandSuggest(text, commandWithSlash, hoverText == null ? null : legacyText(hoverText)); } - public static BaseComponent createCommandSuggest(String text, String commandWithSlash, Chat hoverText) { + public static FormatableChat createCommandSuggest(String text, String commandWithSlash, Chat hoverText) { return createCommandSuggest(legacyText(text), commandWithSlash, hoverText); } - /* package */ static BaseComponent createCommandSuggest(Chat d, String commandWithSlash, Chat hoverText) { + /* package */ static FormatableChat createCommandSuggest(Chat d, String commandWithSlash, Chat hoverText) { FormatableChat c = chat() .clickSuggest(commandWithSlash) .color(Chat.getConfig().commandColor); if (hoverText != null) c.hover(hoverText); - return c.then(d).get(); + return (FormatableChat) c.then(d); } @@ -125,7 +124,7 @@ public class ChatUtil { /** * @param cmdFormat the command with %d inside to be replaced with the page number (must start with slash) */ - public static BaseComponent createPagination(String prefix, String cmdFormat, int currentPage, int nbPages, int nbPagesToDisplay) { + public static Chat createPagination(String prefix, String cmdFormat, int currentPage, int nbPages, int nbPagesToDisplay) { Set pagesToDisplay = new TreeSet<>(); for (int i = 0; i < nbPagesToDisplay && i < nbPages && nbPages - i > 0; i++) { @@ -160,7 +159,7 @@ public class ChatUtil { else first = false; - FormatableChat pDisp = chatComponent(createCommandLink(Integer.toString(page), String.format(cmdFormat, page), "Aller à la page " + page)); + FormatableChat pDisp = (FormatableChat) createCommandLink(Integer.toString(page), String.format(cmdFormat, page), "Aller à la page " + page); if (page == currentPage) { pDisp.color(Chat.getConfig().highlightedCommandColor); } @@ -170,7 +169,7 @@ public class ChatUtil { } - return d.get(); + return d; } @@ -182,10 +181,10 @@ public class ChatUtil { - public static BaseComponent centerText(BaseComponent text, char repeatedChar, ChatColor decorationColor, + public static Chat centerText(Chat text, char repeatedChar, ChatColor decorationColor, boolean console) { - int textWidth = componentWidth(text, console); + int textWidth = componentWidth(text.get(), console); int maxWidth = (console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH; if (textWidth > maxWidth) @@ -206,14 +205,14 @@ public class ChatUtil { if (repeatedChar != ' ') d.then(text(sideChars).color(decorationColor)); - return d.get(); + return d; } - public static BaseComponent leftText(BaseComponent text, char repeatedChar, ChatColor decorationColor, int nbLeft, + public static Chat leftText(Chat text, char repeatedChar, ChatColor decorationColor, int nbLeft, boolean console) { - int textWidth = componentWidth(text, console); + int textWidth = componentWidth(text.get(), console); int maxWidth = (console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH; int repeatedCharWidth = charW(repeatedChar, console, false); int leftWidth = nbLeft * repeatedCharWidth; @@ -229,14 +228,14 @@ public class ChatUtil { if (repeatedChar != ' ') { d.then(text(repeatedChar(repeatedChar, rightNbChar)).color(decorationColor)); } - return d.get(); + return d; } - public static BaseComponent rightText(BaseComponent text, char repeatedChar, ChatColor decorationColor, int nbRight, + public static Chat rightText(Chat text, char repeatedChar, ChatColor decorationColor, int nbRight, boolean console) { - int textWidth = componentWidth(text, console); + int textWidth = componentWidth(text.get(), console); int maxWidth = (console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH; int repeatedCharWidth = charW(repeatedChar, console, false); int rightWidth = nbRight * repeatedCharWidth; @@ -252,13 +251,13 @@ public class ChatUtil { if (repeatedChar != ' ') { d.then(text(repeatedChar(repeatedChar, nbRight)).color(decorationColor)); } - return d.get(); + return d; } - public static BaseComponent emptyLine(char repeatedChar, ChatColor decorationColor, boolean console) { + public static Chat emptyLine(char repeatedChar, ChatColor decorationColor, boolean console) { int count = ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH) / charW(repeatedChar, console, false); - return text(repeatedChar(repeatedChar, count)).color(decorationColor).get(); + return text(repeatedChar(repeatedChar, count)).color(decorationColor); } private static String repeatedChar(char repeatedChar, int count) { @@ -329,6 +328,12 @@ public class ChatUtil { + public static List wrapInLimitedPixelsToChat(String legacyText, int pixelWidth) { + return wrapInLimitedPixels(legacyText, pixelWidth).stream() + .map(t -> legacyText(t)) + .collect(Collectors.toList()); + } + public static List wrapInLimitedPixels(String legacyText, int pixelWidth) { List lines = new ArrayList<>(); @@ -341,7 +346,7 @@ public class ChatUtil { String currentWord = ""; int currentWordSize = 0; boolean bold = false; - boolean firstCharCurrentWorldBold = false; + boolean firstCharCurrentWordBold = false; do { char c = legacyText.charAt(index); @@ -366,7 +371,7 @@ public class ChatUtil { String lastStyle = ChatColorUtil.getLastColors(currentLine); if (currentWord.charAt(0) == ' ') { currentWord = currentWord.substring(1); - currentWordSize -= charW(' ', false, firstCharCurrentWorldBold); + currentWordSize -= charW(' ', false, firstCharCurrentWordBold); } currentLine = (lastStyle.equals("§r") ? "" : lastStyle) + currentWord; currentLineSize = currentWordSize; @@ -377,7 +382,7 @@ public class ChatUtil { } currentWord = ""+c; currentWordSize = charW(c, false, bold); - firstCharCurrentWorldBold = bold; + firstCharCurrentWordBold = bold; } else if (c == '\n') { if (currentLineSize + currentWordSize > pixelWidth && currentLineSize > 0) { // wrap before word @@ -385,7 +390,7 @@ public class ChatUtil { String lastStyle = ChatColorUtil.getLastColors(currentLine); if (currentWord.charAt(0) == ' ') { currentWord = currentWord.substring(1); - currentWordSize -= charW(' ', false, firstCharCurrentWorldBold); + currentWordSize -= charW(' ', false, firstCharCurrentWordBold); } currentLine = (lastStyle.equals("§r") ? "" : lastStyle) + currentWord; currentLineSize = currentWordSize; @@ -402,7 +407,7 @@ public class ChatUtil { currentLineSize = 0; currentWord = ""; currentWordSize = 0; - firstCharCurrentWorldBold = bold; + firstCharCurrentWordBold = bold; } else { currentWord += c; diff --git a/Core/src/main/java/fr/pandacube/lib/core/players/IOnlinePlayer.java b/Core/src/main/java/fr/pandacube/lib/core/players/IOnlinePlayer.java index e97988c..d1c88ea 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/players/IOnlinePlayer.java +++ b/Core/src/main/java/fr/pandacube/lib/core/players/IOnlinePlayer.java @@ -5,6 +5,10 @@ import java.util.UUID; import fr.pandacube.lib.core.chat.Chat; import fr.pandacube.lib.core.db.DBException; +import net.kyori.adventure.identity.Identified; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; import net.md_5.bungee.api.chat.BaseComponent; public interface IOnlinePlayer extends IOffPlayer { @@ -113,7 +117,24 @@ public interface IOnlinePlayer extends IOffPlayer { * the chat is activated. * @param message the message to display. */ + @Deprecated public abstract void sendMessage(BaseComponent message); + + /** + * Display the provided message in the player’s chat, if + * the chat is activated. + * @param message the message to display. + */ + public abstract void sendMessage(Component message); + + /** + * Display the provided message in the player’s chat, if + * the chat is activated. + * @param message the message to display. + */ + public default void sendMessage(ComponentLike message) { + sendMessage(message.asComponent()); + } /** * Display the provided message in the player’s chat, if @@ -121,7 +142,7 @@ public interface IOnlinePlayer extends IOffPlayer { * @param message the message to display */ public default void sendMessage(Chat message) { - sendMessage(message.get()); + sendMessage(message.getAdv()); } /** @@ -134,8 +155,46 @@ public interface IOnlinePlayer extends IOffPlayer { * the sender. This parameter is only there to be transmitted to the client, so client side filtering can * be processed. */ + @Deprecated public abstract void sendMessage(BaseComponent message, UUID sender); + /** + * Display the provided message in the player’s chat, if + * they allows to display CHAT messages + * @param message the message to display. + * @param sender the player causing the send of this message. Client side filtering may occur. + * May be null if we don’t want client filtering, but still consider the message as CHAT message. + * @implNote implementation of this method should not filter the send of the message, based on + * the sender. This parameter is only there to be transmitted to the client, so client side filtering can + * be processed. + */ + public default void sendMessage(Component message, UUID sender) { + sendMessage(message, () -> sender == null ? Identity.nil() : Identity.identity(sender)); + } + + /** + * Display the provided message in the player’s chat, if + * they allows to display CHAT messages + * @param message the message to display. + * @param sender the player causing the send of this message. Client side filtering may occur. + * May be null if we don’t want client filtering, but still consider the message as CHAT message. + * @implNote implementation of this method should not filter the send of the message, based on + * the sender. This parameter is only there to be transmitted to the client, so client side filtering can + * be processed. + */ + public abstract void sendMessage(Component message, Identified sender); + + /** + * Display the provided message in the player’s chat, if + * they allows to display CHAT messages + * @param message the message to display + * @param sender the player causing the send of this message. Client side filtering may occur. + * May be null if we don’t want client filtering, but still consider the message as CHAT message. + */ + public default void sendMessage(ComponentLike message, UUID sender) { + sendMessage(message.asComponent(), sender); + } + /** * Display the provided message in the player’s chat, if * they allows to display CHAT messages @@ -144,7 +203,7 @@ public interface IOnlinePlayer extends IOffPlayer { * May be null if we don’t want client filtering, but still consider the message as CHAT message. */ public default void sendMessage(Chat message, UUID sender) { - sendMessage(message.get(), sender); + sendMessage(message.getAdv(), sender); } /** @@ -152,6 +211,16 @@ public interface IOnlinePlayer extends IOffPlayer { * activated, prepended with the server prefix. * @param message the message to display */ + public default void sendPrefixedMessage(Component message) { + sendMessage(IPlayerManager.prefixedAndColored(message)); + } + + /** + * Display the provided message in the player’s chat, if the chat is + * activated, prepended with the server prefix. + * @param message the message to display + */ + @Deprecated public default void sendPrefixedMessage(BaseComponent message) { sendMessage(IPlayerManager.prefixedAndColored(message)); } @@ -162,7 +231,7 @@ public interface IOnlinePlayer extends IOffPlayer { * @param message the message to display */ public default void sendPrefixedMessage(Chat message) { - sendPrefixedMessage(message.get()); + sendPrefixedMessage(message.getAdv()); } /** @@ -173,8 +242,19 @@ public interface IOnlinePlayer extends IOffPlayer { * @param stay Stay time in tick * @param fadeOut Fade out time in tick */ + @Deprecated public abstract void sendTitle(BaseComponent title, BaseComponent subtitle, int fadeIn, int stay, int fadeOut); + /** + * Display a title in the middle of the screen. + * @param title The big text + * @param subtitle The less big text + * @param fadeIn Fade in time in tick + * @param stay Stay time in tick + * @param fadeOut Fade out time in tick + */ + public abstract void sendTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut); + /** * Display a title in the middle of the screen. * @param title The big text @@ -184,7 +264,7 @@ public interface IOnlinePlayer extends IOffPlayer { * @param fadeOut Fade out time in tick */ public default void sendTitle(Chat title, Chat subtitle, int fadeIn, int stay, int fadeOut) { - sendTitle(title.get(), subtitle.get(), fadeIn, stay, fadeOut); + sendTitle(title.getAdv(), subtitle.getAdv(), fadeIn, stay, fadeOut); } /** diff --git a/Core/src/main/java/fr/pandacube/lib/core/players/IPlayerManager.java b/Core/src/main/java/fr/pandacube/lib/core/players/IPlayerManager.java index 761ea8f..084cd67 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/players/IPlayerManager.java +++ b/Core/src/main/java/fr/pandacube/lib/core/players/IPlayerManager.java @@ -17,6 +17,7 @@ import fr.pandacube.lib.core.chat.Chat; import fr.pandacube.lib.core.db.DB; import fr.pandacube.lib.core.db.DBInitTableException; import fr.pandacube.lib.core.util.Log; +import net.kyori.adventure.text.Component; import net.md_5.bungee.api.chat.BaseComponent; public abstract class IPlayerManager { @@ -98,9 +99,7 @@ public abstract class IPlayerManager + * This method does not restrict the reception of the message to a specific permission. If you + * want to specify a permission, use {@link #broadcast(BaseComponent, boolean, boolean, String)}. + *

+ * This method assumes this message is not caused by a specific player. To specify the source player, use + * {@link #broadcast(BaseComponent, boolean, boolean, UUID)}. + * + * @param message the message to send. + * @param prefix if the server prefix will be prepended to the message. + * @param console if the message must be displayed in the console. + * @throws IllegalArgumentException if message is null. + */ + public static void broadcast(Component message, boolean prefix, boolean console) { broadcast(message, prefix, console, null, null); } @@ -248,7 +274,7 @@ public abstract class IPlayerManagernet.kyori adventure-api + + net.kyori + adventure-text-serializer-plain + diff --git a/Paper/src/main/java/fr/pandacube/lib/paper/util/ItemStackBuilder.java b/Paper/src/main/java/fr/pandacube/lib/paper/util/ItemStackBuilder.java index c789cc0..a52777a 100644 --- a/Paper/src/main/java/fr/pandacube/lib/paper/util/ItemStackBuilder.java +++ b/Paper/src/main/java/fr/pandacube/lib/paper/util/ItemStackBuilder.java @@ -1,5 +1,6 @@ package fr.pandacube.lib.paper.util; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -21,12 +22,41 @@ import net.kyori.adventure.text.format.TextDecoration.State; public class ItemStackBuilder { + /** + * Create a builder with a clone of the provided ItemStack. + * + * The returned builder will not alter the provided ItemStack. + * IF you want to modify the ItemStack with the builder, please use {@link #wrap(ItemStack)}. + * + * @param base the original ItemStack. + * @return the builder + */ public static ItemStackBuilder of(ItemStack base) { - return new ItemStackBuilder(base.clone()); + return wrap(base.clone()); } - + + /** + * Create a builder of a new ItemStack with the specified Material. + * + * @param mat the material of the new builded ItemStack + * @return the builder + */ public static ItemStackBuilder of(Material mat) { - return new ItemStackBuilder(new ItemStack(mat)); + return wrap(new ItemStack(mat)); + } + + /** + * Create a builder that will alter the data of the provided ItemStack. + * + * The {@link #build()} method of thez returned builder will return the same instance + * of ItemStack as the parameter of this method. + * + * To create a builder that doesn’t modify the provided ItemStack, use {@link #of(ItemStack)}. + * @param stack + * @return the builder + */ + public static ItemStackBuilder wrap(ItemStack stack) { + return new ItemStackBuilder(stack); } @@ -95,14 +125,14 @@ public class ItemStackBuilder { return rawLore(Collections.emptyList()); } - public ItemStackBuilder addLoreAfter(List lore) { - if (lore != null) { + public ItemStackBuilder addLoreAfter(List lores) { + if (lores != null) { List baseLore = getOrInitMeta().lore(); if (baseLore == null) baseLore = Collections.emptyList(); return rawLore( Streams.concat( baseLore.stream(), - lore.stream() + lores.stream() .map(line -> Chat.italicFalseIfNotSet(line).getAdv()) ) .collect(Collectors.toList())); @@ -111,6 +141,12 @@ public class ItemStackBuilder { return this; } + public ItemStackBuilder addLoreAfter(Chat... lores) { + if (lores == null || lores.length == 0) + return this; + return addLoreAfter(Arrays.asList(lores)); + } + public ItemStackBuilder enchant(Enchantment ench, int level) { getOrInitMeta().addEnchant(ench, level, true); updateMeta();