Pretty big commit with lot of unrelated changes
This commit is contained in:
309
src/main/java/fr/pandacube/util/text_display/Chat.java
Normal file
309
src/main/java/fr/pandacube/util/text_display/Chat.java
Normal file
@@ -0,0 +1,309 @@
|
||||
package fr.pandacube.util.text_display;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.UUID;
|
||||
|
||||
import fr.pandacube.Pandacube;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.ItemTag;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.hover.content.Content;
|
||||
import net.md_5.bungee.api.chat.hover.content.Entity;
|
||||
import net.md_5.bungee.api.chat.hover.content.Item;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
|
||||
public abstract class Chat extends ChatStatic {
|
||||
|
||||
protected BaseComponent component;
|
||||
protected boolean console = false;
|
||||
|
||||
public Chat(BaseComponent c) {
|
||||
component = c;
|
||||
}
|
||||
|
||||
public BaseComponent get() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public BaseComponent[] getAsArray() {
|
||||
return new BaseComponent[] { component };
|
||||
}
|
||||
|
||||
public String getLegacyText() {
|
||||
return component.toLegacyText();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Chat then(BaseComponent subComponent) {
|
||||
// here are some optimizations to avoid unnecessary component nesting
|
||||
if (subComponent instanceof TextComponent) {
|
||||
TextComponent txtComp = (TextComponent) subComponent;
|
||||
if (!txtComp.hasFormatting() && (txtComp.getText() == null || txtComp.getText().isEmpty())) {
|
||||
// no need to add the provided component to the current component.
|
||||
// but eventual child component must be added
|
||||
if (txtComp.getExtra() != null) {
|
||||
for (BaseComponent child : txtComp.getExtra())
|
||||
then(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
component.addExtra(subComponent);
|
||||
return this;
|
||||
}
|
||||
public Chat then(Chat comp) { return then(comp.get()); }
|
||||
public Chat then(BaseComponent[] components) {
|
||||
if (components != null) {
|
||||
for (BaseComponent c : components) {
|
||||
then(c);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Chat thenText(Object plainText) { return then(text(plainText)); }
|
||||
|
||||
public Chat thenInfo(Object plainText) { return then(infoText(plainText)); }
|
||||
|
||||
public Chat thenSuccess(Object plainText) { return then(successText(plainText)); }
|
||||
|
||||
public Chat thenFailure(Object plainText) { return then(failureText(plainText)); }
|
||||
|
||||
public Chat thenData(Object plainText) { return then(dataText(plainText)); }
|
||||
|
||||
public Chat thenDecoration(Object plainText) { return then(decorationText(plainText)); }
|
||||
|
||||
public Chat thenPlayerName(String legacyText) { return then(playerNameText(legacyText)); }
|
||||
|
||||
public Chat thenNewLine() { return thenText("\n"); }
|
||||
|
||||
public Chat thenLegacyText(Object legacyText) { return then(legacyText(legacyText)); }
|
||||
|
||||
public Chat thenTranslation(String key, Object... with) { return then(translation(key, with)); }
|
||||
|
||||
public Chat thenKeyBind(String key) { return then(keybind(key)); }
|
||||
|
||||
public Chat thenScore(String name, String objective, String value) { return then(score(name, objective, value)); }
|
||||
|
||||
|
||||
|
||||
|
||||
public Chat thenURLLink(Chat inner, String url, Chat hover) { return then(ChatUtil.createURLLink(inner, url, hover)); }
|
||||
public Chat thenURLLink(Chat inner, String url) { return thenURLLink(inner, url, null); }
|
||||
public Chat thenURLLink(String url, Chat hover) { return thenURLLink(text(url), url, hover); }
|
||||
public Chat thenURLLink(String url) { return thenURLLink(text(url), url); }
|
||||
|
||||
public Chat thenCommandLink(Chat inner, String cmdWithSlash, Chat hover) { return then(ChatUtil.createCommandLink(inner, cmdWithSlash, hover)); }
|
||||
public Chat thenCommandLink(Chat inner, String cmdWithSlash) { return thenCommandLink(inner, cmdWithSlash, null); }
|
||||
public Chat thenCommandLink(String cmdWithSlash, Chat hover) { return thenCommandLink(text(cmdWithSlash), cmdWithSlash, hover); }
|
||||
public Chat thenCommandLink(String cmdWithSlash) { return thenCommandLink(text(cmdWithSlash), cmdWithSlash); }
|
||||
|
||||
public Chat thenCommandSuggest(Chat inner, String cmdWithSlash, Chat hover) { return then(ChatUtil.createCommandSuggest(inner, cmdWithSlash, hover)); }
|
||||
public Chat thenCommandSuggest(Chat inner, String cmdWithSlash) { return thenCommandSuggest(inner, cmdWithSlash, null); }
|
||||
public Chat thenCommandSuggest(String cmdWithSlash, Chat hover) { return thenCommandSuggest(text(cmdWithSlash), cmdWithSlash, hover); }
|
||||
public Chat thenCommandSuggest(String cmdWithSlash) { return thenCommandSuggest(text(cmdWithSlash), cmdWithSlash); }
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draws a full line with the default decoration char, colored with the default decoration color.
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public Chat thenEmptyCharLine() {
|
||||
return then(ChatUtil.emptyLine(Pandacube.CHAT_DECORATION_CHAR, Pandacube.CHAT_DECORATION_COLOR, console));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws a full line with the default decoration char, colored with the default decoration color,
|
||||
* and with the provided Chat left aligned on the line, default to the decoration color, and surrounded with 1 space on each side.
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public Chat thenLeftTextCharLine(Chat leftText) {
|
||||
return then(ChatUtil.leftText(chat().decorationColor().thenText(" ").then(leftText).thenText(" ").get(), Pandacube.CHAT_DECORATION_CHAR,
|
||||
Pandacube.CHAT_DECORATION_COLOR, Pandacube.CHAT_NB_CHAR_MARGIN, console));
|
||||
}
|
||||
/**
|
||||
* Draws a full line with the default decoration char, colored with the default decoration color,
|
||||
* and with the provided component left aligned on the line, default to the decoration color, and surrounded with 1 space on each side.
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public Chat thenLeftTextCharLine(BaseComponent leftText) {
|
||||
return thenLeftTextCharLine(chatComponent(leftText));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws a full line with the default decoration char, colored with the default decoration color,
|
||||
* and with the provided Chat right aligned on the line, default to the decoration color, and surrounded with 1 space on each side.
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public Chat thenRightTextCharLine(Chat rightText) {
|
||||
return then(ChatUtil.rightText(chat().decorationColor().thenText(" ").then(rightText).thenText(" ").get(), Pandacube.CHAT_DECORATION_CHAR,
|
||||
Pandacube.CHAT_DECORATION_COLOR, Pandacube.CHAT_NB_CHAR_MARGIN, console));
|
||||
}
|
||||
/**
|
||||
* Draws a full line with the default decoration char, colored with the default decoration color,
|
||||
* and with the provided component right aligned on the line, default to the decoration color, and surrounded with 1 space on each side.
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public Chat thenRightTextCharLine(BaseComponent leftText) {
|
||||
return thenRightTextCharLine(chatComponent(leftText));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws a full line with the default decoration char, colored with the default decoration color,
|
||||
* and with the provided Chat centered on the line, default to the decoration color, and surrounded with 1 space on each side.
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public Chat thenCenterTextCharLine(Chat centerText) {
|
||||
return then(ChatUtil.centerText(chat().decorationColor().thenText(" ").then(centerText).thenText(" ").get(), Pandacube.CHAT_DECORATION_CHAR,
|
||||
Pandacube.CHAT_DECORATION_COLOR, console));
|
||||
}
|
||||
/**
|
||||
* Draws a full line with the default decoration char, colored with the default decoration color,
|
||||
* and with the provided component centered on the line, default to the decoration color, and surrounded with 1 space on each side.
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
public Chat thenCenterTextCharLine(BaseComponent leftText) {
|
||||
return thenCenterTextCharLine(chatComponent(leftText));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static class FormatableChat extends Chat {
|
||||
public FormatableChat(BaseComponent c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public FormatableChat console(boolean c) { console = c; return this; }
|
||||
|
||||
public FormatableChat color(ChatColor c) { component.setColor(c); return this; }
|
||||
public FormatableChat color(Color c) { return color(ChatColor.of(c)); }
|
||||
public FormatableChat color(String c) { return color(ChatColor.of(c)); }
|
||||
|
||||
public FormatableChat black() { return color(ChatColor.BLACK); }
|
||||
public FormatableChat darkBlue() { return color(ChatColor.DARK_BLUE); }
|
||||
public FormatableChat darkGreen() { return color(ChatColor.DARK_GREEN); }
|
||||
public FormatableChat darkAqua() { return color(ChatColor.DARK_AQUA); }
|
||||
public FormatableChat darkRed() { return color(ChatColor.DARK_RED); }
|
||||
public FormatableChat darkPurple() { return color(ChatColor.DARK_PURPLE); }
|
||||
public FormatableChat gold() { return color(ChatColor.GOLD); }
|
||||
public FormatableChat gray() { return color(ChatColor.GRAY); }
|
||||
public FormatableChat darkGray() { return color(ChatColor.DARK_GRAY); }
|
||||
public FormatableChat blue() { return color(ChatColor.BLUE); }
|
||||
public FormatableChat green() { return color(ChatColor.GREEN); }
|
||||
public FormatableChat aqua() { return color(ChatColor.AQUA); }
|
||||
public FormatableChat red() { return color(ChatColor.RED); }
|
||||
public FormatableChat lightPurple() { return color(ChatColor.LIGHT_PURPLE); }
|
||||
public FormatableChat yellow() { return color(ChatColor.YELLOW); }
|
||||
public FormatableChat white() { return color(ChatColor.WHITE); }
|
||||
|
||||
public FormatableChat successColor() { return color(Pandacube.CHAT_SUCCESS_COLOR); }
|
||||
public FormatableChat failureColor() { return color(Pandacube.CHAT_FAILURE_COLOR); }
|
||||
public FormatableChat infoColor() { return color(Pandacube.CHAT_INFO_COLOR); }
|
||||
public FormatableChat dataColor() { return color(Pandacube.CHAT_DATA_COLOR); }
|
||||
public FormatableChat decorationColor() { return color(Pandacube.CHAT_DECORATION_COLOR); }
|
||||
|
||||
public FormatableChat font(String f) { component.setFont(f); return this; }
|
||||
|
||||
public FormatableChat bold(Boolean b) { component.setBold(b); return this; }
|
||||
public FormatableChat bold() { return bold(true); }
|
||||
|
||||
public FormatableChat italic(Boolean i) { component.setItalic(i); return this; }
|
||||
public FormatableChat italic() { return italic(true); }
|
||||
|
||||
public FormatableChat underlined(Boolean u) { component.setUnderlined(u); return this; }
|
||||
public FormatableChat underlined() { return underlined(true); }
|
||||
|
||||
public FormatableChat strikethrough(Boolean s) { component.setStrikethrough(s); return this; }
|
||||
public FormatableChat strikethrough() { return strikethrough(true); }
|
||||
|
||||
public FormatableChat obfuscated(Boolean o) { component.setObfuscated(o); return this; }
|
||||
public FormatableChat obfuscated() { return obfuscated(true); }
|
||||
|
||||
public FormatableChat shiftClickInsertion(String i) { component.setInsertion(i); return this; }
|
||||
|
||||
private FormatableChat clickEvent(ClickEvent e) { component.setClickEvent(e); return this; }
|
||||
private FormatableChat clickEvent(ClickEvent.Action a, String v) { return clickEvent(new ClickEvent(a, v)); }
|
||||
public FormatableChat clickCommand(String cmdWithSlash) { return clickEvent(ClickEvent.Action.RUN_COMMAND, cmdWithSlash); }
|
||||
public FormatableChat clickSuggest(String cmdWithSlash) { return clickEvent(ClickEvent.Action.SUGGEST_COMMAND, cmdWithSlash); }
|
||||
public FormatableChat clickClipboard(String value) { return clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, value); }
|
||||
public FormatableChat clickURL(String url) { return clickEvent(ClickEvent.Action.OPEN_URL, url); }
|
||||
public FormatableChat clickBookPage(int page) { return clickEvent(ClickEvent.Action.CHANGE_PAGE, Integer.toString(page)); }
|
||||
|
||||
private FormatableChat hoverEvent(HoverEvent e) { component.setHoverEvent(e); return this; }
|
||||
private FormatableChat hoverEvent(HoverEvent.Action a, Content v) { return hoverEvent(new HoverEvent(a, v)); }
|
||||
private FormatableChat hoverText(Text v) { return hoverEvent(HoverEvent.Action.SHOW_TEXT, v); }
|
||||
@SuppressWarnings("deprecation")
|
||||
public FormatableChat hoverText(BaseComponent v) {
|
||||
try {
|
||||
return hoverText(new Text( new BaseComponent[] {v}));
|
||||
} catch (NoSuchMethodError e) {
|
||||
return hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[] {v}));
|
||||
}
|
||||
}
|
||||
public FormatableChat hoverText(Chat v) { return hoverText(v.get()); }
|
||||
public FormatableChat hoverText(String legacyText) { return hoverText(legacyText(legacyText)); }
|
||||
private FormatableChat hoverItem(Item v) { return hoverEvent(HoverEvent.Action.SHOW_ITEM, v); }
|
||||
/** @param id namespaced item id */
|
||||
public FormatableChat hoverItem(String id, int stackSize, ItemTag tag) { return hoverItem(new Item(id, stackSize, tag)); }
|
||||
/** @param id namespaced item id */
|
||||
public FormatableChat hoverItem(String id, int stackSize) { return hoverItem(id, stackSize, null); }
|
||||
/** @param id namespaced item id */
|
||||
public FormatableChat hoverItem(String id, ItemTag tag) { return hoverItem(id, -1, tag); }
|
||||
/** @param id namespaced item id */
|
||||
public FormatableChat hoverItem(String id) { return hoverItem(id, -1, null); }
|
||||
public FormatableChat hoverEntity(Entity e) { return hoverEvent(HoverEvent.Action.SHOW_ENTITY, e); }
|
||||
/** @param type namespaced entity type
|
||||
* @param id cannot be null */
|
||||
public FormatableChat hoverEntity(String type, UUID id, BaseComponent displayName) { return hoverEntity(new Entity(type, id.toString(), displayName)); }
|
||||
/** @param type namespaced entity type
|
||||
* @param id cannot be null */
|
||||
public FormatableChat hoverEntity(String type, UUID id) { return hoverEntity(type, id, null); }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* package */ static Object[] filterChatToBaseComponent(Object[] values) {
|
||||
if (values == null)
|
||||
return null;
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
Object v = values[i];
|
||||
if (v instanceof Chat)
|
||||
values[i] = ((Chat) v).get();
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
293
src/main/java/fr/pandacube/util/text_display/ChatColorUtil.java
Normal file
293
src/main/java/fr/pandacube/util/text_display/ChatColorUtil.java
Normal file
@@ -0,0 +1,293 @@
|
||||
package fr.pandacube.util.text_display;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.javatuples.Pair;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
public class ChatColorUtil {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static final String ALL_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoPpRr";
|
||||
public static final String ALL_COLORS = "0123456789AaBbCcDdEeFf";
|
||||
|
||||
|
||||
private static Pattern HEX_COLOR_PATTERN = Pattern.compile("§x(?>§[0-9a-f]){6}", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern ESS_COLOR_PATTERN = Pattern.compile("§#[0-9a-f]{6}", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* Return the legacy format needed to reproduce the format at the end of the provided legacy text.
|
||||
* Supports standard chat colors and formats, BungeeCord Chat rgb format and EssentialsX rgb format.
|
||||
* The RGB value from EssentialsX format is converted to BungeeCord Chat when included in the returned value.
|
||||
* @param legacyText
|
||||
* @return
|
||||
*/
|
||||
public static String getLastColors(String legacyText) {
|
||||
String result = "";
|
||||
int length = legacyText.length();
|
||||
|
||||
for (int index = length - 2; index >= 0; index--) {
|
||||
if (legacyText.charAt(index) == ChatColor.COLOR_CHAR) {
|
||||
|
||||
// detection of rgb color §x§0§1§2§3§4§5
|
||||
String rgb;
|
||||
if (index > 11
|
||||
&& legacyText.charAt(index - 12) == ChatColor.COLOR_CHAR
|
||||
&& (legacyText.charAt(index - 11) == 'x'
|
||||
|| legacyText.charAt(index - 11) == 'X')
|
||||
&& HEX_COLOR_PATTERN.matcher(rgb = legacyText.substring(index - 12, index + 2)).matches()) {
|
||||
result = rgb + result;
|
||||
break;
|
||||
}
|
||||
|
||||
// detection of rgb color §#012345 (and converting it to bungee chat format)
|
||||
if (index < length - 7
|
||||
&& legacyText.charAt(index + 1) == '#'
|
||||
&& ESS_COLOR_PATTERN.matcher(rgb = legacyText.substring(index, index + 8)).matches()) {
|
||||
rgb = "§x§" + rgb.charAt(2) + "§" + rgb.charAt(3)
|
||||
+ "§" + rgb.charAt(4) + "§" + rgb.charAt(5)
|
||||
+ "§" + rgb.charAt(6) + "§" + rgb.charAt(7);
|
||||
result = rgb + result;
|
||||
break;
|
||||
}
|
||||
|
||||
// try detect non-rgb format
|
||||
char colorChar = legacyText.charAt(index + 1);
|
||||
ChatColor legacyColor = getChatColorByChar(colorChar);
|
||||
|
||||
if (legacyColor != null) {
|
||||
result = legacyColor.toString() + result;
|
||||
|
||||
// Once we find a color or reset we can stop searching
|
||||
char col = legacyColor.toString().charAt(1);
|
||||
if ((col >= '0' && col <= '9')
|
||||
|| (col >= 'a' && col <= 'f')
|
||||
|| col == 'r') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ChatColor getChatColorByChar(char code) {
|
||||
return ChatColor.getByChar(Character.toLowerCase(code));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Translate the color code of the provided string, that uses the the color char, to
|
||||
* the {@code §} color code format.
|
||||
* <p>
|
||||
* This method is the improved version of {@link ChatColor#translateAlternateColorCodes(char, String)},
|
||||
* because it takes into account essentials RGB color code, and {@code altColorChar} escaping (by doubling it).
|
||||
* Essentials RGB color code are converted to Bungee chat RGB format, so the returned string can be converted
|
||||
* to component (see {@link Chat#legacyText(Object)}).
|
||||
* <p>
|
||||
* This method should be used for user input (no permission check) or string configuration, but not string
|
||||
* from another API or containing URLs.
|
||||
*/
|
||||
public static String translateAlternateColorCodes(char altColorChar, String textToTranslate)
|
||||
{
|
||||
char colorChar = ChatColor.COLOR_CHAR;
|
||||
StringBuilder acc = new StringBuilder();
|
||||
char[] b = textToTranslate.toCharArray();
|
||||
for ( int i = 0; i < b.length; i++ )
|
||||
{
|
||||
if (i < b.length - 1 // legacy chat format
|
||||
&& b[i] == altColorChar && ALL_CODES.indexOf(b[i + 1]) > -1)
|
||||
{
|
||||
acc.append(colorChar);
|
||||
acc.append(lowerCase(b[i + 1]));
|
||||
i++;
|
||||
}
|
||||
else if (i < b.length - 13 // bungee chat RGB format
|
||||
&& b[i] == altColorChar
|
||||
&& lowerCase(b[i + 1]) == 'x'
|
||||
&& b[i + 2] == altColorChar && ALL_COLORS.indexOf(b[i + 3]) > -1
|
||||
&& b[i + 4] == altColorChar && ALL_COLORS.indexOf(b[i + 5]) > -1
|
||||
&& b[i + 6] == altColorChar && ALL_COLORS.indexOf(b[i + 7]) > -1
|
||||
&& b[i + 8] == altColorChar && ALL_COLORS.indexOf(b[i + 9]) > -1
|
||||
&& b[i + 10] == altColorChar && ALL_COLORS.indexOf(b[i + 11]) > -1
|
||||
&& b[i + 12] == altColorChar && ALL_COLORS.indexOf(b[i + 13]) > -1) {
|
||||
acc.append(colorChar).append(lowerCase(b[i + 1]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 3]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 5]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 7]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 9]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 11]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 13]));
|
||||
i+=13;
|
||||
}
|
||||
else if (i < b.length - 7 // Essentials chat RGB format
|
||||
&& b[i] == altColorChar
|
||||
&& b[i + 1] == '#'
|
||||
&& ALL_COLORS.indexOf(b[i + 2]) > -1 && ALL_COLORS.indexOf(b[i + 3]) > -1
|
||||
&& ALL_COLORS.indexOf(b[i + 4]) > -1 && ALL_COLORS.indexOf(b[i + 5]) > -1
|
||||
&& ALL_COLORS.indexOf(b[i + 6]) > -1 && ALL_COLORS.indexOf(b[i + 7]) > -1) {
|
||||
acc.append(colorChar).append('x');
|
||||
acc.append(colorChar).append(lowerCase(b[i + 2]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 3]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 4]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 5]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 6]));
|
||||
acc.append(colorChar).append(lowerCase(b[i + 7]));
|
||||
i+=7;
|
||||
}
|
||||
else if (i < b.length - 1 && b[i] == altColorChar && b[i + 1] == altColorChar) {
|
||||
acc.append(altColorChar);
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
acc.append(b[i]);
|
||||
}
|
||||
}
|
||||
return acc.toString();
|
||||
}
|
||||
|
||||
private static char lowerCase(char c) { return Character.toLowerCase(c); }
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Force a text to be italic, while keeping other formatting and colors.
|
||||
* The text is prefixed with the ITALIC tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully italic
|
||||
*/
|
||||
public static String forceItalic(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.ITALIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be bold, while keeping other formatting and colors.
|
||||
* The text is prefixed with the BOLD tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully bold
|
||||
*/
|
||||
public static String forceBold(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.BOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be underlined, while keeping other formatting and colors.
|
||||
* The text is prefixed with the UNDERLINE tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully underlined
|
||||
*/
|
||||
public static String forceUnderline(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.UNDERLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be stroked through, while keeping other formatting and colors.
|
||||
* The text is prefixed with the STRIKETHROUGH tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully stroked through
|
||||
*/
|
||||
public static String forceStrikethrough(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.STRIKETHROUGH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be obfuscated, while keeping other formatting and colors.
|
||||
* The text is prefixed with the MAGIC tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully obfuscated
|
||||
*/
|
||||
public static String forceObfuscated(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.MAGIC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String forceFormat(String legacyText, ChatColor format) {
|
||||
return format + legacyText
|
||||
.replace(format.toString(), "") // remove previous tag to make the result cleaner
|
||||
.replaceAll("§([a-frA-FR0-9])", "§$1" + format);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Replace the RESET tag of the input string to the specified color tag.
|
||||
* @param legacyText the original text
|
||||
* @param color the color to used to replace the RESET tag
|
||||
* (can be a combination of a color tag followed by multiple format tag)
|
||||
* @return the resulting text
|
||||
*/
|
||||
public static String resetToColor(String legacyText, String color) {
|
||||
return legacyText.replace(ChatColor.RESET.toString(), color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static ChatColor interpolateColor(float v0, float v1, float v, ChatColor cc0, ChatColor cc1) {
|
||||
Color c0 = cc0.getColor(), c1 = cc1.getColor();
|
||||
int r0 = c0.getRed(), g0 = c0.getGreen(), b0 = c0.getBlue(),
|
||||
r1 = c1.getRed(), g1 = c1.getGreen(), b1 = c1.getBlue();
|
||||
float normV = (v - v0) / (v1 - v0);
|
||||
return ChatColor.of(new Color(
|
||||
(int) (r0 + (r1 - r0) * normV),
|
||||
(int) (g0 + (g1 - g0) * normV),
|
||||
(int) (b0 + (b1 - b0) * normV)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static class ChatValueGradient {
|
||||
List<Pair<Float, ChatColor>> colors = new ArrayList<>();
|
||||
|
||||
public synchronized ChatValueGradient add(float v, ChatColor col) {
|
||||
colors.add(Pair.with(v, col));
|
||||
return this;
|
||||
}
|
||||
|
||||
public synchronized ChatColor pickColorAt(float v) {
|
||||
if (colors.isEmpty())
|
||||
throw new IllegalStateException("Must define at least one color in this ChatValueGradient instance.");
|
||||
if (colors.size() == 1)
|
||||
return colors.get(0).getValue1();
|
||||
|
||||
colors.sort((p1, p2) -> Float.compare(p1.getValue0(), p2.getValue0()));
|
||||
|
||||
if (v <= colors.get(0).getValue0())
|
||||
return colors.get(0).getValue1();
|
||||
if (v >= colors.get(colors.size() - 1).getValue0())
|
||||
return colors.get(colors.size() - 1).getValue1();
|
||||
|
||||
int p1 = 1;
|
||||
for (; p1 < colors.size(); p1++) {
|
||||
if (colors.get(p1).getValue0() >= v)
|
||||
break;
|
||||
}
|
||||
int p0 = p1 - 1;
|
||||
float v0 = colors.get(p0).getValue0(), v1 = colors.get(p1).getValue0();
|
||||
ChatColor cc0 = colors.get(p0).getValue1(), cc1 = colors.get(p1).getValue1();
|
||||
|
||||
return interpolateColor(v0, v1, v, cc0, cc1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
73
src/main/java/fr/pandacube/util/text_display/ChatStatic.java
Normal file
73
src/main/java/fr/pandacube/util/text_display/ChatStatic.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package fr.pandacube.util.text_display;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import fr.pandacube.util.text_display.Chat.FormatableChat;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.KeybindComponent;
|
||||
import net.md_5.bungee.api.chat.Keybinds;
|
||||
import net.md_5.bungee.api.chat.ScoreComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
|
||||
public abstract class ChatStatic {
|
||||
|
||||
|
||||
|
||||
public static FormatableChat chatComponent(BaseComponent c) {
|
||||
return new FormatableChat(c);
|
||||
}
|
||||
|
||||
public static FormatableChat chat() {
|
||||
return chatComponent(new TextComponent());
|
||||
}
|
||||
|
||||
public static FormatableChat chatComponent(BaseComponent[] c) {
|
||||
return chatComponent(new TextComponent(c));
|
||||
}
|
||||
|
||||
public static FormatableChat text(Object plainText) {
|
||||
return chatComponent(new TextComponent(Objects.toString(plainText)));
|
||||
}
|
||||
|
||||
public static FormatableChat legacyText(Object legacyText) {
|
||||
return chatComponent(TextComponent.fromLegacyText(Objects.toString(legacyText), null));
|
||||
}
|
||||
|
||||
public static FormatableChat infoText(Object plainText) {
|
||||
return text(plainText).infoColor();
|
||||
}
|
||||
|
||||
public static FormatableChat dataText(Object plainText) {
|
||||
return text(plainText).dataColor();
|
||||
}
|
||||
|
||||
public static FormatableChat decorationText(Object plainText) {
|
||||
return text(plainText).decorationColor();
|
||||
}
|
||||
|
||||
public static FormatableChat successText(Object plainText) {
|
||||
return text(plainText).successColor();
|
||||
}
|
||||
|
||||
public static FormatableChat failureText(Object plainText) {
|
||||
return text(plainText).failureColor();
|
||||
}
|
||||
|
||||
public static FormatableChat playerNameText(String legacyText) {
|
||||
return legacyText(legacyText).white();
|
||||
}
|
||||
|
||||
public static FormatableChat translation(String key, Object... with) {
|
||||
return chatComponent(new TranslatableComponent(key, Chat.filterChatToBaseComponent(with)));
|
||||
}
|
||||
|
||||
/** @param key one of the values in {@link Keybinds}. */
|
||||
public static FormatableChat keybind(String key) {
|
||||
return chatComponent(new KeybindComponent(key));
|
||||
}
|
||||
|
||||
public static FormatableChat score(String name, String objective, String value) {
|
||||
return chatComponent(new ScoreComponent(name, objective, value));
|
||||
}
|
||||
}
|
@@ -1,5 +1,10 @@
|
||||
package fr.pandacube.util.text_display;
|
||||
|
||||
import static fr.pandacube.util.text_display.Chat.chatComponent;
|
||||
import static fr.pandacube.util.text_display.ChatStatic.chat;
|
||||
import static fr.pandacube.util.text_display.ChatStatic.legacyText;
|
||||
import static fr.pandacube.util.text_display.ChatStatic.text;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -9,12 +14,14 @@ import java.util.TreeSet;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import fr.pandacube.Pandacube;
|
||||
import fr.pandacube.util.text_display.Chat.FormatableChat;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
|
||||
public class DisplayUtil {
|
||||
public class ChatUtil {
|
||||
|
||||
public static final int DEFAULT_CHAR_SIZE = 6;
|
||||
public static final Map<Integer, String> CHARS_SIZE = new ImmutableMap.Builder<Integer, String>()
|
||||
@@ -34,33 +41,31 @@ public class DisplayUtil {
|
||||
public static final int BOOK_WIDTH = 116;
|
||||
|
||||
public static final int CONSOLE_NB_CHAR_DEFAULT = 50;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static final ChatColor COLOR_TITLE = ChatColor.GOLD;
|
||||
public static final ChatColor COLOR_LINK = ChatColor.GREEN;
|
||||
public static final ChatColor COLOR_COMMAND = ChatColor.GRAY;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static BaseComponent createURLLink(String text, String url) {
|
||||
return createURLLink(legacyText(text), url, null);
|
||||
}
|
||||
|
||||
public static BaseComponent createURLLink(String text, String url, String hoverText) {
|
||||
return _createURLLink(new Display(text), url, hoverText);
|
||||
}
|
||||
public static BaseComponent createURLLink(BaseComponent text, String url, String hoverText) {
|
||||
return _createURLLink(new Display(text), url, hoverText);
|
||||
}
|
||||
public static BaseComponent createURLLink(BaseComponent[] text, String url, String hoverText) {
|
||||
return _createURLLink(new Display(text), url, hoverText);
|
||||
return createURLLink(legacyText(text), url, hoverText != null ? legacyText(hoverText) : null);
|
||||
}
|
||||
|
||||
private static BaseComponent _createURLLink(Display d, String url, String hoverText) {
|
||||
/* package */ static BaseComponent createURLLink(Chat element, String url, Chat hover) {
|
||||
String dispURL = (url.length() > 50) ? (url.substring(0, 48) + "...") : url;
|
||||
return d.clickURL(url)
|
||||
.hoverText(ChatColor.GRAY + ((hoverText == null) ? "Cliquez pour accéder au site :" : hoverText) + "\n"
|
||||
+ ChatColor.GRAY + dispURL)
|
||||
.color(COLOR_LINK).get();
|
||||
return chat()
|
||||
.clickURL(url)
|
||||
.color(Pandacube.CHAT_URL_COLOR)
|
||||
.hoverText(
|
||||
hover != null ? hover : Chat.text(dispURL)
|
||||
)
|
||||
.then(element)
|
||||
.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -71,19 +76,19 @@ public class DisplayUtil {
|
||||
|
||||
|
||||
public static BaseComponent createCommandLink(String text, String commandWithSlash, String hoverText) {
|
||||
return createCommandLink(text, commandWithSlash, hoverText == null ? null : TextComponent.fromLegacyText(hoverText));
|
||||
return createCommandLink(text, commandWithSlash, hoverText == null ? null : legacyText(hoverText));
|
||||
}
|
||||
public static BaseComponent createCommandLink(String text, String commandWithSlash, BaseComponent hoverText) {
|
||||
return createCommandLink(text, commandWithSlash, hoverText == null ? null : new BaseComponent[] {hoverText});
|
||||
}
|
||||
public static BaseComponent createCommandLink(String text, String commandWithSlash, BaseComponent[] hoverText) {
|
||||
return _createCommandLink(new Display(text), commandWithSlash, hoverText);
|
||||
public static BaseComponent createCommandLink(String text, String commandWithSlash, Chat hoverText) {
|
||||
return createCommandLink(legacyText(text), commandWithSlash, hoverText);
|
||||
}
|
||||
|
||||
private static BaseComponent _createCommandLink(Display d, String commandWithSlash, BaseComponent[] hoverText) {
|
||||
d.clickCommand(commandWithSlash).color(COLOR_COMMAND);
|
||||
if (hoverText != null) d.hoverText(hoverText);
|
||||
return d.get();
|
||||
/* package */ static BaseComponent createCommandLink(Chat d, String commandWithSlash, Chat hoverText) {
|
||||
FormatableChat c = chat()
|
||||
.clickCommand(commandWithSlash)
|
||||
.color(Pandacube.CHAT_COMMAND_COLOR);
|
||||
if (hoverText != null)
|
||||
c.hoverText(hoverText);
|
||||
return c.then(d).get();
|
||||
}
|
||||
|
||||
|
||||
@@ -96,19 +101,19 @@ public class DisplayUtil {
|
||||
|
||||
|
||||
public static BaseComponent createCommandSuggest(String text, String commandWithSlash, String hoverText) {
|
||||
return createCommandSuggest(text, commandWithSlash, hoverText == null ? null : TextComponent.fromLegacyText(hoverText));
|
||||
return createCommandSuggest(text, commandWithSlash, hoverText == null ? null : legacyText(hoverText));
|
||||
}
|
||||
public static BaseComponent createCommandSuggest(String text, String commandWithSlash, BaseComponent hoverText) {
|
||||
return createCommandSuggest(text, commandWithSlash, hoverText == null ? null : new BaseComponent[] {hoverText});
|
||||
}
|
||||
public static BaseComponent createCommandSuggest(String text, String commandWithSlash, BaseComponent[] hoverText) {
|
||||
return _createCommandSuggest(new Display(text), commandWithSlash, hoverText);
|
||||
public static BaseComponent createCommandSuggest(String text, String commandWithSlash, Chat hoverText) {
|
||||
return createCommandSuggest(legacyText(text), commandWithSlash, hoverText);
|
||||
}
|
||||
|
||||
private static BaseComponent _createCommandSuggest(Display d, String commandWithSlash, BaseComponent[] hoverText) {
|
||||
d.clickSuggest(commandWithSlash).color(COLOR_COMMAND);
|
||||
if (hoverText != null) d.hoverText(hoverText);
|
||||
return d.get();
|
||||
/* package */ static BaseComponent createCommandSuggest(Chat d, String commandWithSlash, Chat hoverText) {
|
||||
FormatableChat c = chat()
|
||||
.clickSuggest(commandWithSlash)
|
||||
.color(Pandacube.CHAT_COMMAND_COLOR);
|
||||
if (hoverText != null)
|
||||
c.hoverText(hoverText);
|
||||
return c.then(d).get();
|
||||
}
|
||||
|
||||
|
||||
@@ -134,32 +139,33 @@ public class DisplayUtil {
|
||||
pagesToDisplay.add(i);
|
||||
}
|
||||
|
||||
Display d = new Display(prefix);
|
||||
Chat d = chat().thenLegacyText(prefix);
|
||||
boolean first = true;
|
||||
int previous = 0;
|
||||
|
||||
for (int page : pagesToDisplay) {
|
||||
if (!first) {
|
||||
if (page == previous + 1) {
|
||||
d.next(" ");
|
||||
d.thenText(" ");
|
||||
}
|
||||
else {
|
||||
if (cmdFormat.endsWith("%d")) {
|
||||
d.next(" ");
|
||||
d.next(createCommandSuggest("...", cmdFormat.substring(0, cmdFormat.length() - 2), "Choisir la page"));
|
||||
d.next(" ");
|
||||
d.thenText(" ");
|
||||
d.then(createCommandSuggest("...", cmdFormat.substring(0, cmdFormat.length() - 2), "Choisir la page"));
|
||||
d.thenText(" ");
|
||||
}
|
||||
else
|
||||
d.next(" ... ");
|
||||
d.thenText(" ... ");
|
||||
}
|
||||
}
|
||||
else
|
||||
first = false;
|
||||
|
||||
d.next(createCommandLink(Integer.toString(page), String.format(cmdFormat, page), "Aller à la page " + page));
|
||||
FormatableChat pDisp = chatComponent(createCommandLink(Integer.toString(page), String.format(cmdFormat, page), "Aller à la page " + page));
|
||||
if (page == currentPage) {
|
||||
d.color(ChatColor.WHITE);
|
||||
pDisp.color(Pandacube.CHAT_COMMAND_HIGHLIGHTED_COLOR);
|
||||
}
|
||||
d.then(pDisp);
|
||||
|
||||
previous = page;
|
||||
}
|
||||
@@ -175,33 +181,31 @@ public class DisplayUtil {
|
||||
|
||||
|
||||
|
||||
// TODO refaire les 4 methodes ci-dessous
|
||||
|
||||
|
||||
|
||||
|
||||
public static BaseComponent centerText(BaseComponent text, char repeatedChar, ChatColor decorationColor,
|
||||
boolean console) {
|
||||
|
||||
int textWidth = strWidth(text.toPlainText(), console, false);
|
||||
if (textWidth > ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH)) return text;
|
||||
int textWidth = componentWidth(text, console);
|
||||
int maxWidth = (console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH;
|
||||
|
||||
if (textWidth > maxWidth)
|
||||
return text;
|
||||
|
||||
int repeatedCharWidth = charW(repeatedChar, console, false);
|
||||
int sideWidth = (maxWidth - textWidth) / 2;
|
||||
int sideNbChar = sideWidth / repeatedCharWidth;
|
||||
|
||||
if (sideNbChar == 0)
|
||||
return text;
|
||||
|
||||
String sideChars = repeatedChar(repeatedChar, sideNbChar);
|
||||
|
||||
String current = text.toPlainText();
|
||||
int count = 0;
|
||||
do {
|
||||
count++;
|
||||
current = repeatedChar + current + repeatedChar;
|
||||
} while (strWidth(current, console, false) <= ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH));
|
||||
count--;
|
||||
|
||||
String finalLeftOrRight = "";
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
finalLeftOrRight += repeatedChar;
|
||||
|
||||
Display d = new Display().next(finalLeftOrRight).color(decorationColor).next(text);
|
||||
|
||||
if (repeatedChar != ' ') d.next(finalLeftOrRight).color(decorationColor);
|
||||
Chat d = Chat.chat()
|
||||
.then(text(sideChars).color(decorationColor))
|
||||
.then(text);
|
||||
if (repeatedChar != ' ')
|
||||
d.then(text(sideChars).color(decorationColor));
|
||||
|
||||
return d.get();
|
||||
|
||||
@@ -209,91 +213,60 @@ public class DisplayUtil {
|
||||
|
||||
public static BaseComponent leftText(BaseComponent text, char repeatedChar, ChatColor decorationColor, int nbLeft,
|
||||
boolean console) {
|
||||
|
||||
int textWidth = strWidth(text.toPlainText(), console, false);
|
||||
if (textWidth > ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH) || textWidth
|
||||
+ nbLeft * charW(repeatedChar, console, false) > ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH))
|
||||
|
||||
int textWidth = componentWidth(text, console);
|
||||
int maxWidth = (console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH;
|
||||
int repeatedCharWidth = charW(repeatedChar, console, false);
|
||||
int leftWidth = nbLeft * repeatedCharWidth;
|
||||
|
||||
if (textWidth + leftWidth > maxWidth)
|
||||
return text;
|
||||
|
||||
Display d = new Display();
|
||||
|
||||
String finalLeft = "";
|
||||
if (nbLeft > 0) {
|
||||
for (int i = 0; i < nbLeft; i++)
|
||||
finalLeft += repeatedChar;
|
||||
d.next(finalLeft).color(decorationColor);
|
||||
}
|
||||
d.next(text);
|
||||
|
||||
int count = 0;
|
||||
String current = finalLeft + text.toPlainText();
|
||||
do {
|
||||
count++;
|
||||
current += repeatedChar;
|
||||
} while (strWidth(current, console, false) <= ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH));
|
||||
count--;
|
||||
|
||||
int rightNbChar = (maxWidth - (textWidth + leftWidth)) / repeatedCharWidth;
|
||||
|
||||
Chat d = chat()
|
||||
.then(text(repeatedChar(repeatedChar, nbLeft)).color(decorationColor))
|
||||
.then(text);
|
||||
if (repeatedChar != ' ') {
|
||||
String finalRight = "";
|
||||
for (int i = 0; i < count; i++)
|
||||
finalRight += repeatedChar;
|
||||
d.next(finalRight).color(decorationColor);
|
||||
d.then(text(repeatedChar(repeatedChar, rightNbChar)).color(decorationColor));
|
||||
}
|
||||
|
||||
return d.get();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static BaseComponent rightText(BaseComponent text, char repeatedChar, ChatColor decorationColor, int nbRight,
|
||||
boolean console) {
|
||||
|
||||
int textWidth = strWidth(text.toPlainText(), console, false);
|
||||
if (textWidth > ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH) || textWidth
|
||||
+ nbRight * charW(repeatedChar, console, false) > ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH))
|
||||
|
||||
int textWidth = componentWidth(text, console);
|
||||
int maxWidth = (console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH;
|
||||
int repeatedCharWidth = charW(repeatedChar, console, false);
|
||||
int rightWidth = nbRight * repeatedCharWidth;
|
||||
|
||||
if (textWidth + rightWidth > maxWidth)
|
||||
return text;
|
||||
|
||||
String tempText = text.toPlainText();
|
||||
if (nbRight > 0) {
|
||||
tempText += decorationColor;
|
||||
for (int i = 0; i < nbRight; i++)
|
||||
tempText += repeatedChar;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
String current = tempText;
|
||||
do {
|
||||
count++;
|
||||
current = repeatedChar + current;
|
||||
} while (strWidth(current, console, false) <= ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH));
|
||||
count--;
|
||||
|
||||
String finalLeft = "";
|
||||
for (int i = 0; i < count; i++)
|
||||
finalLeft += repeatedChar;
|
||||
|
||||
Display d = new Display().next(finalLeft).color(decorationColor).next(text);
|
||||
|
||||
int leftNbChar = (maxWidth - (textWidth + rightWidth)) / repeatedCharWidth;
|
||||
|
||||
Chat d = chat()
|
||||
.then(text(repeatedChar(repeatedChar, leftNbChar)).color(decorationColor))
|
||||
.then(text);
|
||||
if (repeatedChar != ' ') {
|
||||
String finalRight = "";
|
||||
for (int i = 0; i < nbRight; i++)
|
||||
finalRight += repeatedChar;
|
||||
d.next(finalRight).color(decorationColor);
|
||||
d.then(text(repeatedChar(repeatedChar, nbRight)).color(decorationColor));
|
||||
}
|
||||
|
||||
return d.get();
|
||||
|
||||
}
|
||||
|
||||
public static BaseComponent emptyLine(char repeatedChar, ChatColor decorationColor, boolean console) {
|
||||
int count = ((console) ? CONSOLE_NB_CHAR_DEFAULT : DEFAULT_CHAT_WIDTH) / charW(repeatedChar, console, false);
|
||||
String finalLine = "";
|
||||
for (int i = 0; i < count; i++)
|
||||
finalLine += repeatedChar;
|
||||
|
||||
return new Display().next(finalLine).color(decorationColor).get();
|
||||
return text(repeatedChar(repeatedChar, count)).color(decorationColor).get();
|
||||
}
|
||||
|
||||
|
||||
private static String repeatedChar(char repeatedChar, int count) {
|
||||
char[] c = new char[count];
|
||||
Arrays.fill(c, repeatedChar);
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -304,13 +277,23 @@ public class DisplayUtil {
|
||||
|
||||
|
||||
public static int componentWidth(BaseComponent[] components, boolean console) {
|
||||
return Arrays.stream(components).mapToInt(c -> componentWidth(c, console)).sum();
|
||||
if (components == null)
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (BaseComponent c : components)
|
||||
count += componentWidth(c, console);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static int componentWidth(BaseComponent component, boolean console) {
|
||||
if (component == null)
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
for (BaseComponent c : component.getExtra())
|
||||
count += componentWidth(c, console);
|
||||
|
||||
if (component instanceof TextComponent) {
|
||||
count += strWidth(((TextComponent)component).getText(), console, component.isBold());
|
||||
}
|
||||
@@ -318,6 +301,11 @@ public class DisplayUtil {
|
||||
for (BaseComponent c : ((TranslatableComponent)component).getWith())
|
||||
count += componentWidth(c, console);
|
||||
}
|
||||
|
||||
if (component.getExtra() != null) {
|
||||
for (BaseComponent c : component.getExtra())
|
||||
count += componentWidth(c, console);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -368,14 +356,15 @@ public class DisplayUtil {
|
||||
if ((c >= '0' && c <= '9') // reset bold
|
||||
|| (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'A' && c <= 'F')
|
||||
|| c == 'r' || c == 'R')
|
||||
|| c == 'r' || c == 'R'
|
||||
|| c == 'x' || c == 'X')
|
||||
bold = false;
|
||||
|
||||
}
|
||||
else if (c == ' ') {
|
||||
if (currentLineSize + currentWordSize > pixelWidth && currentLineSize > 0) { // wrap before word
|
||||
lines.add(currentLine);
|
||||
String lastStyle = getLastColors(currentLine);
|
||||
String lastStyle = ChatColorUtil.getLastColors(currentLine);
|
||||
if (currentWord.charAt(0) == ' ') {
|
||||
currentWord = currentWord.substring(1);
|
||||
currentWordSize -= charW(' ', false, firstCharCurrentWorldBold);
|
||||
@@ -394,7 +383,7 @@ public class DisplayUtil {
|
||||
else if (c == '\n') {
|
||||
if (currentLineSize + currentWordSize > pixelWidth && currentLineSize > 0) { // wrap before word
|
||||
lines.add(currentLine);
|
||||
String lastStyle = getLastColors(currentLine);
|
||||
String lastStyle = ChatColorUtil.getLastColors(currentLine);
|
||||
if (currentWord.charAt(0) == ' ') {
|
||||
currentWord = currentWord.substring(1);
|
||||
currentWordSize -= charW(' ', false, firstCharCurrentWorldBold);
|
||||
@@ -408,7 +397,7 @@ public class DisplayUtil {
|
||||
}
|
||||
// wrap after
|
||||
lines.add(currentLine);
|
||||
String lastStyle = getLastColors(currentLine);
|
||||
String lastStyle = ChatColorUtil.getLastColors(currentLine);
|
||||
|
||||
currentLine = lastStyle.equals("§r") ? "" : lastStyle;
|
||||
currentLineSize = 0;
|
||||
@@ -438,123 +427,46 @@ public class DisplayUtil {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static String getLastColors(String legacyText) {
|
||||
String result = "";
|
||||
int length = legacyText.length();
|
||||
|
||||
// Search backwards from the end as it is faster
|
||||
for (int index = length - 1; index > -1; index--) {
|
||||
char section = legacyText.charAt(index);
|
||||
if (section == ChatColor.COLOR_CHAR && index < length - 1) {
|
||||
char c = legacyText.charAt(index + 1);
|
||||
ChatColor color = getChatColorByChar(c);
|
||||
|
||||
if (color != null) {
|
||||
result = color.toString() + result;
|
||||
|
||||
// Once we find a color or reset we can stop searching
|
||||
char col = color.toString().charAt(1);
|
||||
if ((col >= '0' && col <= '9')
|
||||
|| (col >= 'a' && col <= 'f')
|
||||
|| col == 'r') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ChatColor getChatColorByChar(char code) {
|
||||
return ChatColor.getByChar(Character.toLowerCase(code));
|
||||
}
|
||||
|
||||
|
||||
public static String truncatePrefix(String prefix, int maxLength) {
|
||||
if (prefix.length() > maxLength) {
|
||||
String lastColor = ChatColorUtil.getLastColors(prefix);
|
||||
prefix = truncateAtLengthWithoutReset(prefix, maxLength);
|
||||
if (!ChatColorUtil.getLastColors(prefix).equals(lastColor))
|
||||
prefix = truncateAtLengthWithoutReset(prefix, maxLength - lastColor.length()) + lastColor;
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
public static String truncateAtLengthWithoutReset(String prefix, int l) {
|
||||
if (prefix.length() > l) {
|
||||
prefix = prefix.substring(0, l);
|
||||
if (prefix.endsWith("§"))
|
||||
prefix = prefix.substring(0, prefix.length()-1);
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Force a text to be italic, while keeping other formatting and colors.
|
||||
* The text is prefixed with the ITALIC tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully italic
|
||||
*/
|
||||
public static String forceItalic(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.ITALIC);
|
||||
|
||||
public static BaseComponent toUniqueBaseComponent(BaseComponent... baseComponents) {
|
||||
if (baseComponents == null || baseComponents.length == 0)
|
||||
return new TextComponent();
|
||||
if (baseComponents.length == 1)
|
||||
return baseComponents[0];
|
||||
return new TextComponent(baseComponents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be bold, while keeping other formatting and colors.
|
||||
* The text is prefixed with the BOLD tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully bold
|
||||
*/
|
||||
public static String forceBold(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.BOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be underlined, while keeping other formatting and colors.
|
||||
* The text is prefixed with the UNDERLINE tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully underlined
|
||||
*/
|
||||
public static String forceUnderline(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.UNDERLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be stroked through, while keeping other formatting and colors.
|
||||
* The text is prefixed with the STRIKETHROUGH tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully stroked through
|
||||
*/
|
||||
public static String forceStrikethrough(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.STRIKETHROUGH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a text to be obfuscated, while keeping other formatting and colors.
|
||||
* The text is prefixed with the MAGIC tag, but is not reset at the end.
|
||||
* @param legacyText the original text
|
||||
* @return the text fully obfuscated
|
||||
*/
|
||||
public static String forceObfuscated(String legacyText) {
|
||||
return forceFormat(legacyText, ChatColor.MAGIC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String forceFormat(String legacyText, ChatColor format) {
|
||||
return format + legacyText
|
||||
.replace(format.toString(), "") // remove previous tag to make the result cleaner
|
||||
.replaceAll("§([a-frA-FR0-9])", "§$1" + format);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Replace the RESET tag of the input string to the specified color tag.
|
||||
* @param legacyText the original text
|
||||
* @param color the color to used to replace the RESET tag
|
||||
* (can be a combination of a color tag followed by multiple format tag)
|
||||
* @return the resulting text
|
||||
*/
|
||||
public static String resetToColor(String legacyText, String color) {
|
||||
return legacyText.replace(ChatColor.RESET.toString(), color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,331 +0,0 @@
|
||||
package fr.pandacube.util.text_display;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
public class Display {
|
||||
|
||||
private BaseComponent root = new TextComponent("");
|
||||
|
||||
private BaseComponent current = null;
|
||||
|
||||
|
||||
/*
|
||||
* ****************
|
||||
* * Constructors *
|
||||
* ****************
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance. The current component is not initialized.
|
||||
*/
|
||||
public Display() {}
|
||||
|
||||
/**
|
||||
* Create a new instance, with the current component already initialized with the parameter.
|
||||
* @param legacyText a text that will be converted to a component and set to the current compoment.
|
||||
*/
|
||||
public Display(String legacyText) {
|
||||
next(legacyText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance, with the current component already initialized with the parameter.
|
||||
* @param legacyText a list of text that will be joined by a line return followed by ChatColor.RESET,
|
||||
* then converted to a component and set to the current component.
|
||||
*/
|
||||
public Display(List<String> legacyText) {
|
||||
this(String.join("\n"+ChatColor.RESET, legacyText));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance, with the current component already initialized with the parameter.
|
||||
* @param legacyText an array of text that will be joined by a line return followed by ChatColor.RESET,
|
||||
* then converted to a component and set to the current component.
|
||||
*/
|
||||
public Display(String[] legacyText) {
|
||||
this(Arrays.asList(legacyText));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance, with the current component already initialized with the parameter.
|
||||
* @param firstComponent a component corresponding to the current component.
|
||||
*/
|
||||
public Display(BaseComponent firstComponent) {
|
||||
next(firstComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance, with the current component already initialized with the parameter.
|
||||
* @param components an array of component that will be inside the current component.
|
||||
*/
|
||||
public Display(BaseComponent[] components) {
|
||||
if (components == null) throw new IllegalArgumentException("le paramètre ne doit pas être null");
|
||||
next(components);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ******************
|
||||
* * next() methods *
|
||||
* ******************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize the current component with the parameter.
|
||||
* The previous component is stored in the root component.
|
||||
* @param cmp a component corresponding to the new component.
|
||||
* @return this
|
||||
*/
|
||||
public Display next(BaseComponent cmp) {
|
||||
if (cmp == null) throw new IllegalArgumentException("le paramètre ne doit pas être null");
|
||||
finalizeCurrentComponent();
|
||||
current = cmp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the current component with the parameter.
|
||||
* The previous component is stored in the root component.
|
||||
* @param str a text that will be converted to a component and set to the current compoment.
|
||||
* @return this
|
||||
*/
|
||||
public Display next(String str) {
|
||||
return next(TextComponent.fromLegacyText(str == null ? "" : str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the current component with the parameter.
|
||||
* The previous component is stored in the root component.
|
||||
* @param components an array of component that will be inside the current component.
|
||||
* @return this
|
||||
*/
|
||||
public Display next(BaseComponent[] components) {
|
||||
if (components != null && components.length == 1)
|
||||
return next(components[0]);
|
||||
|
||||
BaseComponent bc = new TextComponent();
|
||||
for (BaseComponent c : components)
|
||||
bc.addExtra(c);
|
||||
return next(bc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the current component with the parameter.
|
||||
* The previous component is stored in the root component.
|
||||
* @param cmp an other instance of Display that the root component become the current component of this instance.
|
||||
* @return this
|
||||
*/
|
||||
public Display next(Display cmp) {
|
||||
if (cmp == null) throw new IllegalArgumentException("le paramètre ne doit pas être null");
|
||||
return next(cmp.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the current component with the text "\n".
|
||||
* The previous component is stored in the root component.
|
||||
* @return this
|
||||
*/
|
||||
public Display nextLine() {
|
||||
finalizeCurrentComponent();
|
||||
current = new TextComponent("\n");
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* **************************
|
||||
* * Style and behaviour of *
|
||||
* *** current component ****
|
||||
* **************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set the color of the current component.
|
||||
* @param color the colour. Can be null;
|
||||
* @return this
|
||||
*/
|
||||
public Display color(ChatColor color) {
|
||||
current.setColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the current component is bold.
|
||||
* @param b true if bold, false if not, null if undefined
|
||||
* @return this
|
||||
*/
|
||||
public Display bold(Boolean b) {
|
||||
current.setBold(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the current component is italic.
|
||||
* @param b true if italic, false if not, null if undefined
|
||||
* @return this
|
||||
*/
|
||||
public Display italic(Boolean i) {
|
||||
current.setItalic(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the current component is underlined.
|
||||
* @param b true if underlined, false if not, null if undefined
|
||||
* @return this
|
||||
*/
|
||||
public Display underlined(Boolean u) {
|
||||
current.setUnderlined(u);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the current component is obfuscated.
|
||||
* In Minecraft user interface, obfuscated text displays randomly generated character in place of the originals. The random text regenerate each frame.
|
||||
* @param b true if obfuscated, false if not, null if undefined
|
||||
* @return this
|
||||
*/
|
||||
public Display obfuscated(Boolean o) {
|
||||
current.setObfuscated(o);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the current component is strikethrough.
|
||||
* @param b true if strikethrough, false if not, null if undefined
|
||||
* @return this
|
||||
*/
|
||||
public Display strikethrough(Boolean s) {
|
||||
current.setStrikethrough(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a text displayed as a tooltip when the cursor is hover the current component.
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat or in a book
|
||||
* @param content the text as an array of component.
|
||||
* @return this
|
||||
*/
|
||||
public Display hoverText(BaseComponent[] content) {
|
||||
current.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a text displayed as a tooltip when the cursor is hover the current component.
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat or in a book
|
||||
* @param content the text as a component
|
||||
* @return this
|
||||
*/
|
||||
public Display hoverText(BaseComponent content) {
|
||||
return hoverText(new BaseComponent[] {content});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a text displayed as a tooltip when the cursor is hover the current component.
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat or in a book
|
||||
* @param content the text as a legacy string.
|
||||
* @return this
|
||||
*/
|
||||
public Display hoverText(String legacyContent) {
|
||||
return hoverText(TextComponent.fromLegacyText(legacyContent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a text displayed as a tooltip when the cursor is hover the current component.
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat or in a book
|
||||
* @param content the text as a {@link Display} instance.
|
||||
* @return this
|
||||
*/
|
||||
public Display hoverText(Display content) {
|
||||
return hoverText(content.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the player to click on the current component to access to the specified URL.
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat
|
||||
* @param url the URL
|
||||
* @return this
|
||||
*/
|
||||
public Display clickURL(String url) {
|
||||
current.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the player to click on the current component to copy content to the clipboard.
|
||||
* @param str the string to copy to clipboard
|
||||
* @return this
|
||||
*/
|
||||
public Display clickClipboard(String str) {
|
||||
current.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, str));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the player to click on the current component to run the specified command.
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat, in a book or on a sign.
|
||||
* On the sign, all the commands are executed in a row when the player click on the sign.
|
||||
* @param cmd the command, with the "/"
|
||||
* @return this
|
||||
*/
|
||||
public Display clickCommand(String cmd) {
|
||||
current.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, cmd));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the player to click on the current component to fill the textfield with the specified command.
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat.
|
||||
* @param cmd the command
|
||||
* @return this
|
||||
*/
|
||||
public Display clickSuggest(String cmd) {
|
||||
current.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, cmd));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the player to shuft-click on the current component to insert the specified string into the textfield (at the cursor location).
|
||||
* This method is only relevant if this Display is intended to be displayed in the chat.
|
||||
* @param str the string
|
||||
* @return this
|
||||
*/
|
||||
public Display clickInsertion(String str) {
|
||||
current.setInsertion(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void finalizeCurrentComponent() {
|
||||
if (current != null) root.addExtra(current);
|
||||
current = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the current compoment into the root component and return the root component.
|
||||
* @return
|
||||
*/
|
||||
public BaseComponent get() {
|
||||
finalizeCurrentComponent();
|
||||
if (!root.hasFormatting() && root.getExtra() != null && root.getExtra().size() == 1)
|
||||
return root.getExtra().get(0);
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the current compoment into the root component and return all the components in an array.
|
||||
* @return
|
||||
*/
|
||||
public BaseComponent[] getArray() {
|
||||
finalizeCurrentComponent();
|
||||
return root.getExtra().toArray(new BaseComponent[root.getExtra().size()]);
|
||||
}
|
||||
|
||||
}
|
@@ -6,7 +6,6 @@ public class TextProgressBar {
|
||||
private static String pattern_start = "[";
|
||||
private static String pattern_end = "]";
|
||||
private static ChatColor color_empty = ChatColor.DARK_GRAY;
|
||||
private static ChatColor color_decoration = ChatColor.GOLD;
|
||||
private static ChatColor color_default = ChatColor.RESET;
|
||||
private static String pattern_empty = ".";
|
||||
private static String pattern_full = "|";
|
||||
@@ -35,7 +34,7 @@ public class TextProgressBar {
|
||||
}
|
||||
int sum_sizes = 0;
|
||||
|
||||
String bar = color_decoration + pattern_start;
|
||||
String bar = pattern_start;
|
||||
for (int i = 0; i < sizes.length; i++) {
|
||||
sum_sizes += sizes[i];
|
||||
|
||||
@@ -52,7 +51,7 @@ public class TextProgressBar {
|
||||
for (int j = 0; j < (max_size - sum_sizes); j++)
|
||||
bar = bar + pattern_empty;
|
||||
|
||||
bar = bar + color_decoration + pattern_end;
|
||||
bar = bar + ChatColor.RESET + pattern_end;
|
||||
return bar;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user