Util JSON Messages, Titles and Actionbars | No NMS!

Discussion in 'Resources' started by Rayzr522, Sep 28, 2016.

Thread Status:
Not open for further replies.
  1. Offline

    Rayzr522

    Hello and welcome!

    I don't know how many of you heard of it, but a while ago there was a library called Fanciful. Sadly it's no longer being updated. I have way too much time on my hands, so I figured why not recreate it from scratch?

    Enter: JSONMessage. This is a near replication of Fanciful, with the message building system and method names nearly identical. However, I have updated mine, and I've also added features for actually sending the messages as both JSON chat messages and titles. All of this comes packaged in one fully-documented class file.

    There are tons of examples on the GitHub page, but I'll give a couple simple ones. Here's how you would make a simple message with text that displays when you hover:
    Code:
    JSONMessage.create("Go to the ")
                 .color(ChatColor.GOLD)
               .then("best website ever!")
                 .color(ChatColor.BLUE)
                 .tooltip("Click to go")
                 .openURL("http://www.youtube.com/");
    As an added bonus, this also will open YouTube when you click on it ;)

    For those of you that used Fanciful before, this system shouldn't be difficult to understand. It's almost exactly the same, but you can actually send the messages now:
    Code:
    JSONMessage.create("Go to the ")
                 .color(ChatColor.GOLD)
               .then("best website ever!")
                 .color(ChatColor.BLUE)
                 .tooltip("Click to go")
                 .openURL("http://www.youtube.com/")
               .send(player);
    You can give the send method as many player objects as you want. To send titles it's nearly the same:
    Code:
    JSONMessage.create("I am a title")
                 .color(ChatColor.GREEN)
                 .style(ChatColor.ITALIC)
               .title(10, 20, 10, player);
    And for subtitles you just do the same thing without the int parameters:
    Code:
    JSONMessage.create("I am a title")
                 .color(ChatColor.GREEN)
                 .style(ChatColor.ITALIC)
               .title(10, 20, 10, player);
    
    JSONMessage.create("A wild subtitle has appeared!")
                 .color(ChatColor.GOLD)
               .subtitle(player);
    All of these examples are shown on the GitHub page too, and they're explained in much more detail. There's also a method reference on that page.

    Note: all of my code uses Reflection instead of NMS, so this should work in ANY version (1.7+), and theoretically it should continue working in the future. If Mojang changes how the protocol works then I'll adapt it.

    There are a few things I haven't implemented yet, such as a show_item hover event, but it is fully functional and has almost everything.


    I loved making this, and I hope it'll be of use to someone.

    - Rayzr :D
     
    Last edited: Sep 29, 2016
  2. Offline

    Rayzr522

    In case anyone cares, this now has actionbar support too. Go check out the GitHub page to see how, I have examples there.
     
  3. Offline

    RingOfStorms

    Nice utility.

    One neat function that would be a useful addition would be an automatic function for centering text in a line/message.

    Here is a neat little class that does this with single messages. Because minecraft's font is not monospaced you have to take in account different pixel widths of characters which is what that terrible looking function is. There is probably a nicer elegant way you might be able to condense it all into.

    Code:
    public static String strJoin (String delim, Collection list) {
        return strJoin(delim, false, list);
    }
    
    public static String strJoin (String delim, boolean endSpace, Collection list) {
        if(list == null)
            return null;
        else if(list.size() == 0)
            return "";
        else {
            StringBuilder sb = new StringBuilder();
            for(Object o : list) {
                sb.append(o.toString());
                sb.append(delim);
            }
            sb.delete(sb.length()-delim.length(), sb.length());
            if(endSpace)
                sb.append(' ');
            return sb.toString();
        }
    }
    
    public static void sendCenteredMessage (CommandSender sender, String... messages) {
        for(String message : messages) {
            if (message == null || message.trim().isEmpty()) {
                sender.sendMessage("");
                return;
            }
    
            sender.sendMessage(getCenteringCompensation(message, 154) + message);
        }
    }
    
    public static String repeat (String str, int times) {
        return new String(new char[times]).replace("\0", str);
    }
    
    public static UUID uuidFromString (String str) {
        if(str.length() == 36)
            try {
                return UUID.fromString(str);
            }catch (Exception badUuidProvided) {}
        else
            try {
                StringBuffer buffer = new StringBuffer(str.trim());
                char delim = '-';
                for(int pos : new int[] {20, 16, 12, 8})
                    buffer.insert(pos, delim);
                return UUID.fromString(buffer.toString());
            }catch (Exception badUuidProvided) {}
        return null;
    }
    
    public static int getPixelSize (char c) {
        if(c == 'i' || c == 'l' || c == '!' || c == ':' || c == ';' || c == '\'' || c == '|' ||
                c == '.' || c == ',')
            return 1;
        else if(c == 'I' || c == '[' || c == ']' || c == '"' || c == '`' || c == ' ')
            return 3;
        else if(c == 'f' || c == 'k' || c == 't' || c == '(' || c == ')' || c == '{' || c == '}' ||
                c == '<' || c == '>')
            return 4;
        else if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'B') || (c >= '0' && c <= '9') ||
                (c >= '#' && c <= '&') || c == '*' || c == '+' || c == '-' || c == '=' ||
                c == '?' || c == '/' || c == '\\')
            return 5;
        else if(c == '@')
            return 6;
        else
            return 4;
    }
    
    public static int getPixelSize (String str) {
        if(str == null)
            return 0;
    
        int messagePxSize = 0;
        boolean previousCode = false;
        boolean isBold = false;
    
        for(char c : str.toCharArray()) {
            if(c == ChatColor.COLOR_CHAR)
                previousCode = true;
            else if(previousCode) {
                previousCode = false;
                char nc = Character.toLowerCase(c);
                if(!isBold) {
                    if (nc == ChatColor.BOLD.getChar())
                        isBold = true;
                }else if(nc == ChatColor.RESET.getChar())
                    isBold = false;
            }else{
                messagePxSize += getPixelSize(c);
                messagePxSize += isBold ? 2 : 1;
            }
        }
    
        return messagePxSize;
    }
    
    public static String getCenteringCompensation (String str, int width) {
        return repeat(" ", (int) Math.ceil((width - (getPixelSize(str)/2))/4d));
    }
     
  4. Offline

    Rayzr522

    Thanks!

    Just curious, could you clarify exactly what you're talking about centering? The entire message? Just one message part? Just the current line of text (so it would walk backwards in the message parts till it hits a newline)?
     
  5. Offline

    I Al Istannen

    @Rayzr522 @RingOfStorms
    This.
    Just center a line of text. You can't center multiple lines, so center one line.
    The code from Fishy is probably a bit nicer, though Set's would be more appropiate than the Lists he used. Just make a static "asSet" method to ease creation.

    (And Fanciful works on 1.10 with more features (item tooltip and stuff)) :p
     
  6. Offline

    Rayzr522

    I've seen his code, and it would certainly be very useful. Also you can center multiple lines of text, you just have to center each line individually. Wouldn't be easy, but it sure would be cool :p

    Also who cares if Fanciful works in 1.10? Why use something that already exists when you can reinvent it! :D
     
  7. Offline

    RenditionsRule

    @Rayzr522
    Because that would be the same as reinventing the wheel, something that already exists and benefits us. All wheels are the same, and for the most part, they aren't different when it comes to functionality.
     
  8. Offline

    Rayzr522

    @RenditionsRule

    ...I was being sarcastic... and it is beneficial for me to recreate it as a learning experience if nothing else.
     
  9. Offline

    DoggyCode™

    Well. I'm a simple man and just use Bukkits perform command method to execute the "tellraw Player JSONSTRING"


    Sent from my iPhone using Tapatalk
     
Thread Status:
Not open for further replies.

Share This Page