[LIB] Fanciful: pleasant chat message formatting

Discussion in 'Resources' started by mkremins, Nov 15, 2013.

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

    libraryaddict

    Garris0n likes this.
  2. Offline

    AmoebaMan

    I already tried to get him to merge a reflection-using PR. He's decided he'd rather continue without it.
     
  3. Offline

    mkremins

    Just merged in a pull request to update the Bukkit/CB deps. Update to Fanciful 0.1.4-SNAPSHOT and you should be good to go.

    This is correct, although I'm open to being convinced otherwise if switching over to reflection will make downstream users' lives substantially easier.
     
  4. Offline

    Blah1

    mkremins Is it possible to append things in a StringBuilder (including a FancyMessage) and sending to the player in a way that the JSON parts work?

    What I mean:

    Code:java
    1. StringBuilder sb = new StringBuilder();
    2. for (String s : plugin.getConfig().getConfigurationSection("items.").getKeys(false)) {
    3. sb.append(WordUtils.capitalizeFully(new FancyMessage(s).color(WHITE).tooltip("Click to get the " + plugin.getItem().getFormalName(s.toLowerCase())).suggest("/item" + s).toJSONString())).append(ChatColor.DARK_AQUA).append(", ").append(ChatColor.WHITE);
    4. }
    5. plugin.send(sender, "item-usage", sb.substring(0, sb.length() - 4));
     
  5. Offline

    mkremins

    As it stands, the code you've posted almost certainly won't work the way you expect it to. The problem is that FancyMessage.toJSONString() returns raw JSON, and simply concatenating raw JSON with a chat color code isn't sufficient to recolor the message that the JSON string encodes.

    I don't know exactly what your code is trying to do, but off the top of my head, it might be possible to rewrite it to look something like this:
    Code:
    FancyMessage fm = new FancyMessage("");
    for (String s : plugin.getConfig().getConfigurationSection("items.").getKeys(false)) {
      fm.then(s)
          .color(WHITE)
          .tooltip("Click to get the " + plugin.getItem().getFormalName(s.toLowerCase()))
          .suggest("/item " + s)
        .then(", ")
          .color(DARK_AQUA);
    }
    fm.send(sender);
    Of course, this is a really naïve solution – among other things, it doesn't slice off the trailing comma in the comma-separated list like your StringBuilder code would – but the basic principle at work here is that you can call FancyMessage.then(String s) to append a new section to an existing FancyMessage object, at which point any formatting methods you call will apply to the message part you most recently appended.

    I actually found this problem quite interesting from an API design perspective. It's hard to write what I think you're trying to write elegantly using Fanciful, and that seems to point out some weak spots in the Fanciful API that I'd previously overlooked. I'll be thinking about this in greater depth in the future.
     
  6. Offline

    confuserr

    It means that any bug fixes you push from now on will require using 1.7.5 craftbukkit (1.7 R2). Not all of us update our servers straight away, by using reflection you can add support for older versions and potentially newer ones without the need of an update (emphasis on potentially). So by not using reflection, if I want to use this library on my network once https://github.com/mkremins/fanciful/issues/6 is fixed, I'll have to update to 1.7.5 which is currently only a development build and isn't considered as stable.
     
  7. Offline

    AmoebaMan


    If you're sending the message as a raw string, this won't work. The Minecraft client does not actually automatically parse the JSON messages the same way that it automatically parses the color codes - it actually requires a completely separate packet to be sent.

    At least, I think that's the case. Either way, it doesn't work.
     
  8. Offline

    Garris0n

    I have to agree with this. I'm normally fairly against using reflection instead of just raw NMS, but in this case, being a library that people on multiple versions may be using, it seems pretty necessary. That said, I am worried about what kind of performance hit might be taken when it's switched to reflection, especially since there may be cases when it's being used very constantly to send a lot of chat messages.
     
  9. Offline

    Blah1

    mkremins Just what I was thinking of. Thanks man.

    One more thing. If I were to be sending a lot of FancyMessage to a bunch of players, would it make the server laggy? Just wondering how much more intensive these messages are than just normal player.sendMessage
     
  10. Offline

    mkremins

    Alright, in this case I think I see the need for reflection. I'll take a look at merging one of the existing pull requests or implementing it myself.

    I'm pretty sure the code used by CraftBukkit/NMS to send "ordinary" chat messages actually ends up calling the code that's used to send JSON-encoded chat messages. If this is in fact the case, there shouldn't be any significant performance issues with sending FancyMessages as opposed to sending plain text.
     
  11. Offline

    elementalgodz11

    mkremins
    Will you be adding a way to append other FancyMessages into a FancyMessage?

    I have also tried setting a multi line hover text using a String array[] without any errors in the IDE however the hover shows the message "Invalid Item".

    Thanks.
     
  12. Offline

    mkremins

    It's not currently on my radar; do you have a specific use-case that would benefit from being able to do this?

    You're likely running into this issue, which is the result of a bug in Minecraft's internal JSON parser that causes it to freak out upon encountering an item lore string that contains a colon. Until a workaround is implemented in Fanciful itself, you should be able to get around this bug by avoiding the use of colons in multiline tooltips.

    libraryaddict AmoebaMan confuserr Garris0n (and anyone else who was waiting on the switch to reflection):

    As of this commit, I'm using reflection to get NMS/OBC deps instead of hardcoding them in. I've also pushed a snapshot build to the Maven repo to reflect the change.

    The current implementation uses AmeobaMan's reflection utils class. Thanks to everyone who contributed code and ideas to the discussion about reflection and got me to change my mind :)

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 29, 2015
  13. Offline

    Blah1

    mkremins Is it possible to have multiple lines of text for .tooltip("")?
    I tried doing them back to back like .tooltip().tooltip() and it didn'y work and putting "\n" in them makes it say "Invalid item!"
     
  14. Offline

    mkremins

    There's several ways to do a multiline tooltip: you can pass in a single string with newlines, an array of strings, or any other Iterable<String> to the tooltip method. However, multiline tooltips are currently partially broken (see this issue for details) because of a bug in Minecraft's internal JSON parser. As a temporary workaround for the bug, you can remove colons from your tooltip strings, at which point multiline tooltips should work as expected using any of the aforementioned methods.
     
  15. Offline

    Blah1

    mkremins Still getting the "Invalid Item!" bug. I update to the latest version of FancyMessage and tried all the ways you listed but none work. (List<String> actually throws an error)

    You know what would be cool? If it was possible to do anything on click event instead of just a command suggestion or a command.

    Something like fm.do({player.sendMessage("hi"); player.setHealth(20.0);})
    But idk if that's possible.
     
  16. Offline

    Garris0n

    It would sort-of be possible I suppose.
     
  17. Offline

    mkremins

    Hmm, would you mind posting or sending me the exact code you're trying to make work? I haven't heard any other reports of issues with multiline tooltips that don't involve the Minecraft JSON parser bug, and I'd like to get a better idea of what might be causing the problems you're experiencing.

    You can sorta-kinda do this already with the FancyMessage.command(String) method – just write a custom command that runs whatever code you want to run, then pass that command as an argument to the .command() method. When the relevant message part is clicked, the player will execute your custom command, which will in turn call whatever code you set it up to run.

    This is, of course, a fairly ugly way of making this behavior happen, and I could definitely see myself moving the common implementation code for such a system into the Fanciful API at some point in the future. It'd be a fairly large-scale feature to implement, though, and I don't see it being addressed (unless someone wants to make a pull request) until well after I've spent some time fixing the present bugs and building any smaller features that happen to crop up.
     
  18. Offline

    Garris0n

    mkremins A system that generates a random string of characters as a command and caches it for a while combined with a listener for the command preprocess event actually wouldn't make it that hard to implement. It would require registering Fanciful as a listener, though, which seems kind-of...strange.
     
  19. Offline

    AmoebaMan

    Blah1 mkremins I sort of cloned/overhauled/adapted this into my own personal utils library, and I remember I fixed the multi-line tooltips at some point. I'll go back and see what I did, and maybe shoot you a PR.
     
  20. Offline

    killje

    @mkremings I wonder if I could make the then function also a null function where you could later add the text. this is because in my plugin i now have to store make-up in a separate file and then convert that again in the fancy message.
    just wondering if it is a direction you would like to take
     
  21. Offline

    mkremins

    Just to clarify, are you talking about something like this? If so, then yeah, I could definitely get behind that idea.
     
  22. Offline

    killje

    haha thank you, that is indeed what i meant, this will help greatly to make my plugin more object oriented.
     
  23. Offline

    mkremins

    Merged in the change and released v0.1.5.
     
    killje and Garris0n like this.
  24. Offline

    killje

    i have send a pull request where one is able to add styles one at the time as well as the previous all of them.
     
  25. Offline

    mkremins

    Merged this in as well. No immediate point release this time around, but you can update to 0.1.6-SNAPSHOT for the time being to get a fresh build :)
     
  26. Offline

    killje

    thank you, this is the last step for my plugin to have no stored information inside a class only to add it later to the fancimessage
     
    mkremins likes this.
  27. Offline

    desht


    Toni slightly late response, I know, but this can also be resolved by correctly declaring the scope for each dependency declared in your POM. A dependency like Bukkit will be provided at run-time, so its scope should always be declared as <scope>provided</scope>. Omitting the scope will default to a scope of "compile".

    When Maven does its dependency-shading, any dependency of scope "provided" will not be shaded into the JAR, because they are assumed to be provided at run-time. That's appropriate for Bukkit (the CraftBukkit server provides it), and any dependencies on plugins which will be present at run-time. But for libraries that are shaded in (like Fanciful), a scope of "compile" is what's needed, and in that case, Maven will include the classes in your JAR.
     
    Toni and mkremins like this.
  28. Offline

    Toni

    desht thank you for clearing that up for me. I probably should now change all of my <scope>compile</scope> for Bukkit to provided. However I have a question, it seems that even when I have scope set to compile, it's not included into my actual plugin?
     
  29. Offline

    desht

    You'd need to be both using shading and have the dependency declared with "compile" scope for it to be pulled into your JAR.
     
    Toni likes this.
  30. Offline

    bobacadodl

    The mutliline hover messages arent working for me either.
    Code:
    Code:
    FancyMessage message = new FancyMessage(
                    rpgPlayer.getName())
                    .color(rpgPlayer.getRank().getColor())
                    .tooltip(
                            rpgPlayer.getName(),
                            rpgPlayer.getRpgClass().getName(),
                            "Level " + Integer.toString(rpgPlayer.getLevel()))
                    .command("/loe player " + rpgPlayer.getName())
                    .then(" \u00bb ").color(ChatColor.WHITE)
                    .then(event.getMessage()).color(rpgPlayer.getChatMode().getColor());
    Example json Output:
    Code:
    {"text":"","extra":[{"text":"justin_393","color":"dark_red","clickEvent":{"action":"run_command","value":"/loe player justin_393"},"hoverEvent":{"action":"show_item","value":"{\"id\":1,\"tag\":{\"display\":{\"Name\":\"\\\\u00A7fjustin_393\",\"Lore\":[\"Mage\",\"Level 1\"]}}}"}},{"text":" » ","color":"white"},{"text":"back","color":"white"}]}
    Output of makeMultiLineTooltip()

    Code:
    {"id":1,"tag":{"display":{"Name":"\\u00A7fjustin_393","Lore":["Mage","Level 1"]}}}
    The message sends successfully, but when I hover over the text, it says "Invalid item" in red
     
Thread Status:
Not open for further replies.

Share This Page