StarShadow

MC - Spigot Rich Text

Jul 4th, 2016 (edited)
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.15 KB | None | 0 0
  1. import net.md_5.bungee.api.chat.*;
  2. import org.bukkit.ChatColor;
  3. import org.bukkit.entity.Player;
  4.  
  5. import java.util.ArrayList;
  6. import java.util.Collection;
  7. import java.util.List;
  8. import java.util.regex.Matcher;
  9. import java.util.regex.Pattern;
  10. import java.util.stream.Collector;
  11. import java.util.stream.Stream;
  12.  
  13. /*
  14.  
  15.     Easily create fancy text in spigot.
  16.     For example text that displays text when you hover over it or runs a command when you click it.
  17.  
  18.     To create a Text object use the method Text.of(String) or the constructor new Text(String)
  19.  
  20.     The input string should have color codes ALREADY TRANSLATED.
  21.  
  22.     To add hover text or run a command when clicked you use brackets.
  23.     Brackets follow the format: {type=value}TEXT{/}
  24.     To use multiple effects on a text just chain the beginning brackets, the single ending bracket counts for all of them.
  25.     Example: {type1=value1}{type2=value2}{type3=value3}TEXT{/}
  26.     If you want to color the text in the bracket make sure you do it INSIDE the bracket or it won't be colored.
  27.  
  28.     Example to add hover text:
  29.     "§7You have been promoted to {hover=§eLeader is the highest rank on the server}§4LEADER{/}§7."
  30.  
  31.     Example to make player run command when text clicked:
  32.     "§7Click {cmd=/sg join sg-1}§eHERE{/} §7to go to SG."
  33.  
  34.     Example with multiple effects on text:
  35.     "§7You muted {hover=§bClick to unmute.}{cmd=/unmute Notch}§aNotch{/}§7.
  36.  
  37.  */
  38.  
  39. public class Text {
  40.    
  41.     private static final String REGEX = "(?:" + ChatColor.COLOR_CHAR + "[A-Fa-fK-Ok-oRr0-9])+[^" + ChatColor.COLOR_CHAR + "]*(?:(?!" + ChatColor.COLOR_CHAR + "[A-Fa-fK-Ok-oRr0-9])[^" + ChatColor.COLOR_CHAR + "]*)*|[^" + ChatColor.COLOR_CHAR + "]*(?:" + ChatColor.COLOR_CHAR + "(?![A-Fa-fK-Ok-oRr0-9])[^" + ChatColor.COLOR_CHAR + "]*)*";
  42.    
  43.     private BaseComponent[] out;
  44.     private List<TextPart> list = new ArrayList<>();
  45.    
  46.     public Text(String text) {
  47.         int index = 0;
  48.         Matcher m = BracketPart.PATTERN.matcher(text);
  49.         while (m.find()) {
  50.             int s = m.start();
  51.             if (s > index) {
  52.                 addParts(text.substring(index, s));
  53.             }
  54.             List<TextPart> l = BracketPart.toTextParts(m.group());
  55.             if (l != null) list.addAll(l);
  56.             index = m.end();
  57.         }
  58.         if (index < text.length()) {
  59.             addParts(text.substring(index));
  60.         }
  61.     }
  62.    
  63.     public Text(Text other) {
  64.         list.addAll(other.list);
  65.     }
  66.    
  67.     @Override
  68.     public String toString() {
  69.         if (out == null) return "";
  70.         StringBuilder builder = new StringBuilder();
  71.         for (BaseComponent component : out) {
  72.             ClickEvent clickEvent = component.getClickEvent();
  73.             HoverEvent hoverEvent = component.getHoverEvent();
  74.             if (clickEvent != null) {
  75.                 builder.append("{");
  76.                 switch (clickEvent.getAction()) {
  77.                     case OPEN_FILE:
  78.                         builder.append("file");
  79.                         break;
  80.                     case OPEN_URL:
  81.                         builder.append("url");
  82.                         break;
  83.                     case RUN_COMMAND:
  84.                         builder.append("cmd");
  85.                         break;
  86.                     case SUGGEST_COMMAND:
  87.                         builder.append("suggest");
  88.                         break;
  89.                     default:
  90.                         break;
  91.                 }
  92.                 builder.append("=").append(clickEvent.getValue()).append("}");
  93.             }
  94.             if (hoverEvent != null) {
  95.                 builder.append("{hover=").append(Stream.of(hoverEvent.getValue()).map(component1 -> component1.toLegacyText()).collect(Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString))).append("}");
  96.             }
  97.             builder.append(component.toLegacyText());
  98.             if (clickEvent != null || hoverEvent != null) builder.append("{/}");
  99.         }
  100.         return builder.toString();
  101.     }
  102.    
  103.     public static Text of(String text) {
  104.         return new Text(text);
  105.     }
  106.    
  107.     public static BaseComponent[] parse(String input) {
  108.         return Text.of(input).build();
  109.     }
  110.    
  111.     private void addParts(String text) {
  112.         //getParts(text)
  113.         list.addAll(getParts(text));
  114.     }
  115.    
  116.     private static List<TextPart> getParts(String input) {
  117.         List<TextPart> l = new ArrayList<>();
  118.         int index = 0;
  119.         Matcher m = Pattern.compile(REGEX).matcher(input);
  120.         while (m.find()) {
  121.             if (!m.group().isEmpty()) {
  122.                 String group = input.substring(index, m.start()) + m.group();
  123.                 if (TextUtils.none(group).isEmpty()) continue;
  124.                 l.add(new TextPart(group));
  125.                 index = m.end();
  126.             }
  127.         }
  128.         if (index < input.length()) l.add(new TextPart(input.substring(index)));
  129.         return l;
  130.     }
  131.    
  132.     private static BaseComponent[] build(List<TextPart> input) {
  133.         ComponentBuilder c = null;
  134.         for (TextPart part : input) {
  135.             if (part == null) continue;
  136.             TextComponent com = part.toComponent();
  137.             if (c == null) c = new ComponentBuilder(com.getText());
  138.             else c.append(com.getText(), ComponentBuilder.FormatRetention.NONE);
  139.             c.color(com.getColor());
  140.             c.bold(com.isBold());
  141.             c.italic(com.isItalic());
  142.             c.underlined(com.isUnderlined());
  143.             c.obfuscated(com.isObfuscated());
  144.             c.strikethrough(com.isStrikethrough());
  145.             if (com.getClickEvent() != null) c.event(com.getClickEvent());
  146.             if (com.getHoverEvent() != null) c.event(com.getHoverEvent());
  147.         }
  148.         if (c != null) return c.create();
  149.         return null;
  150.     }
  151.    
  152.     public BaseComponent[] build() {
  153.         BaseComponent[] tout = build(list);
  154.         if (tout == null) return null;
  155.         out = tout;
  156.         return out;
  157.     }
  158.    
  159.     public void send(Player player) {
  160.         if (out == null) build();
  161.         player.spigot().sendMessage(out);
  162.     }
  163.    
  164.     public void send(Collection<Player> coll) {
  165.         for (Player player : coll) {
  166.             send(player);
  167.         }
  168.     }
  169.    
  170.     public List<String> getParts() {
  171.         List<String> l = new ArrayList<>();
  172.         for (TextPart part : list) {
  173.             l.add(part.getRaw());
  174.         }
  175.         return l;
  176.     }
  177.    
  178.     private static class TextPart {
  179.         private final String text;
  180.         private ClickEvent click = null;
  181.         private HoverEvent hover = null;
  182.        
  183.         TextPart(String t) {
  184.             text = t;
  185.         }
  186.        
  187.         String getRaw() {
  188.             return text;
  189.         }
  190.        
  191.         void setClickEvent(ClickEvent event) {
  192.             click = event;
  193.         }
  194.        
  195.         void setHoverEvent(HoverEvent event) {
  196.             hover = event;
  197.         }
  198.        
  199.         TextComponent toComponent() {
  200.             List<ChatColor> colors = TextUtils.getColors(text);
  201.             TextComponent c = new TextComponent(TextUtils.none(text));
  202.             for (ChatColor color : colors) {
  203.                 if (color.isColor()) c.setColor(TextUtils.convert(color));
  204.                 else {
  205.                     switch (color) {
  206.                         case BOLD:
  207.                             c.setBold(true);
  208.                             break;
  209.                         case ITALIC:
  210.                             c.setItalic(true);
  211.                             break;
  212.                         case UNDERLINE:
  213.                             c.setUnderlined(true);
  214.                             break;
  215.                         case MAGIC:
  216.                             c.setObfuscated(true);
  217.                             break;
  218.                         case STRIKETHROUGH:
  219.                             c.setStrikethrough(true);
  220.                             break;
  221.                         case RESET:
  222.                             c.setColor(net.md_5.bungee.api.ChatColor.WHITE);
  223.                             c.setBold(false);
  224.                             c.setItalic(false);
  225.                             c.setUnderlined(false);
  226.                             c.setObfuscated(false);
  227.                             c.setStrikethrough(false);
  228.                             break;
  229.                         default:
  230.                             break;
  231.                     }
  232.                 }
  233.             }
  234.             if (click != null) {
  235.                 c.setClickEvent(click);
  236.             }
  237.             if (hover != null) {
  238.                 c.setHoverEvent(hover);
  239.             }
  240.             return c;
  241.         }
  242.     }
  243.    
  244.     private static class BracketPart {
  245.         static final Pattern PATTERN = Pattern.compile("\\{(.+?)=(.+?)}(.+?)\\{/}");
  246.         static final Pattern BRACKET = Pattern.compile("\\{(.+?)=(.+?)}");
  247.        
  248.         static List<TextPart> toTextParts(String bracket) {
  249.             if (!bracket.matches(PATTERN.pattern())) return null;
  250.             List<TextPart> l = new ArrayList<>();
  251.             String text = bracket.replaceAll("(?:\\{.+?=.+?})+(.+?)\\{/}", "$1");
  252.             if (text.isEmpty()) return null;
  253.             l.addAll(getParts(text));
  254.             Matcher m = BRACKET.matcher(bracket);
  255.             while (m.find()) {
  256.                 setEvents(l, m.group(1), m.group(2));
  257.             }
  258.             return l;
  259.         }
  260.        
  261.         static void setEvents(List<TextPart> parts, String type, String data) {
  262.             ClickEvent click = null;
  263.             HoverEvent hover = null;
  264.             if (type.equalsIgnoreCase("url")) {
  265.                 click = new ClickEvent(ClickEvent.Action.OPEN_URL, data);
  266.             }
  267.             else if (type.equalsIgnoreCase("file")) {
  268.                 click = new ClickEvent(ClickEvent.Action.OPEN_FILE, data);
  269.             }
  270.             else if (type.equalsIgnoreCase("cmd")) {
  271.                 click = new ClickEvent(ClickEvent.Action.RUN_COMMAND, data);
  272.             }
  273.             else if (type.equalsIgnoreCase("suggest")) {
  274.                 click = new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, data);
  275.             }
  276.             else if (type.equalsIgnoreCase("hover")) {
  277.                 hover = new HoverEvent(HoverEvent.Action.SHOW_TEXT, build(getParts(data)));
  278.             }
  279.             else return;
  280.             for (TextPart part : parts) {
  281.                 if (click != null) part.setClickEvent(click);
  282.                 if (hover != null) part.setHoverEvent(hover);
  283.             }
  284.         }
  285.     }
  286.    
  287.     private static class TextUtils {
  288.         private static List<ChatColor> getColors(String input) {
  289.             input = ChatColor.translateAlternateColorCodes('&', input);
  290.             input = ChatColor.getLastColors(input);
  291.             List<ChatColor> out = new ArrayList<>();
  292.             Matcher m = Pattern.compile(ChatColor.COLOR_CHAR + "([A-Fa-fK-Ok-oRr0-9])").matcher(input);
  293.             while (m.find()) {
  294.                 if (!m.group(1).isEmpty()) {
  295.                     out.add(ChatColor.getByChar(m.group(1)));
  296.                 }
  297.             }
  298.             return out;
  299.         }
  300.        
  301.         private static String color(String i) {
  302.             return ChatColor.translateAlternateColorCodes('&', i);
  303.         }
  304.        
  305.         private static String none(String i) {
  306.             return ChatColor.stripColor(color(i));
  307.         }
  308.        
  309.         private static net.md_5.bungee.api.ChatColor convert(ChatColor color) {
  310.             return net.md_5.bungee.api.ChatColor.getByChar(color.getChar());
  311.         }
  312.     }
  313.    
  314. }
Add Comment
Please, Sign In to add comment