Solved Running a command when chat message is clicked.

Discussion in 'Plugin Development' started by RedCoder4, Oct 7, 2016.

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

    RedCoder4

    Hi all,

    Just wondering if anyone knows to make It when a player clicks a part of the chat it will execute a command. I am making a tpa plugin and when someone gets a request they can click on Accept and it will run /tpaccept and to deny /tpdeny.

    I thought this might work but I do not know.

    Code:
    TextComponent c = new TextComponent("accept!");
                        c.setUnderlined(true);
                        c.setColor(ChatColor.AQUA);
                        c.setClickEvent(new ClickEvent(Action.RUN_COMMAND, "tpaccept"));
                        c.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Accept!").create()));
                        TextComponent msg = new TextComponent("");
                        msg.addExtra(c);
                        target.spigot().sendMessage(msg);
    
    Any help is much appreciated.
     
  2. Offline

    MrGeneralQ

    You have to use Json formats for that.


    Normally I don't spoongive code, but here is a great tutorial on how to do it. But please don't just copy paste it. Listen carefully and try to understand the json format.

    UPDATE: it seems to be outdated. Take a look at github.
     
  3. Offline

    I Al Istannen

  4. Offline

    RedCoder4

    @MrGeneralQ Would never copy and paste. @I Al Istannen I had a look and with openURL would I change it something like runCommand?
     
  5. Offline

    I Al Istannen

    @RedCoder4
    Yes, you would use the "runCommand" method instead of "openURL".
     
  6. Offline

    Rayzr522

    @RedCoder4
    The GitHub page explains everything and also has a method overview: https://github.com/Rayzr522/JSONMessage

    You can see how to do all of it there.

    EDIT: Also, the benefit of my library is you don't have to use version-specific or Spigot-specific code. Yay Reflection!

    EDIT 2: I say Spigot-specific because TextComponent is a Spigot thing.

    And oh my, I just looked at the OP, the Spigot way is... ew. Painful. No. No offense Spigot, your way of doing JSON messages is ugly ;)

    EDIT 3.14: I'm accumulating quite a few edits, aren't I? Anyways, I just also wanted to point out that my team and I (specifically @ZP18 and I) made the same thing you are :p

    The only thing is that ours "attaches" to a separate plugin, basically it attaches to any plugin which has a /tpa (and|or /tpahere) command (you can configure it to work with most plugins). Still, making it from scratch is good experience, whether you're an n00b or an experienced dev.

    EDIT 4: So yeah, you should still make your plugin. The experience is worth the work. Also I should stop editing this post...

    There I go again. I made another wall o' text post ᄑ_ᄑ

    EDIT 5: I lied, one more edit. You'd want something generally like this (you'd have to tweak it):

    Code:
    JSONMessage.create("Accept")
                 .color(ChatColor.GREEN)
                 .tooltip("Click to accept")
                 .runCommand("/tpaccept")
               .send(player);
    EDIT 6: Just one more! I just wanted to say, please nobody hate me for spoon-feeding. That is all.
     
    Last edited: Oct 8, 2016
  7. Offline

    RedCoder4

    @I Al Istannen Ah ok. @Rayzr522 Will try this. I do appreciate you do all those edits just to help me. However, another question. How do I go by adding a dent json? Just do the same like the accept and put it under the other message?
     
  8. Offline

    Rayzr522

    Yup! Just change "Accept" to "Deny", and probably also change ChatColor.GREEN to ChatColor.RED

    Also another thing you could do is:

    Code:
    JSONMessage.create("Accept")
                 .color(ChatColor.GREEN)
                 .tooltip("Click to accept")
                 .runCommand("/tpaccept")
               .then(" or ")
                 .color(ChatColor.GRAY)
                 .style(ChatColor.BOLD)
               .then("Deny")
                 .color(ChatColor.RED)
                 .tooltip("Click to deny")
                 .runCommand("/tpdeny")
               .send(player);
     
  9. Offline

    mythbusterma

    @Rayzr522

    So the idea is that you deliberately defeat the protections that Bukkit added to the server by using reflection? Why? You can't guarantee that the code won't change between versions of the Minecraft server, so you can't guarantee that this will continue working. That's why they implemented the version specific packaging in the first place. Using reflection to get around this safety is lazy at best.
     
    blue1 likes this.
  10. @mythbusterma
    Why is using reflection lazy? I don't understand your reasoning. If you just used NMS code without reflection, then you're absolutely certain it'll break in the next update, while if you use reflection, it's quite a high chance it won't break. So yes, you're going to have to update it, but if you do use reflection you won't have to do it for every small new update mojang release (1.10, which really just added blocks and mobs). Not to mention that the code for these chat formats has stayed the same for years.
     
  11. Offline

    I Al Istannen

    @mythbusterma
    The code uses craftbukkit code which will most likely not change, as it implements Bukkit. Then it uses deobfuscated NMS code, which will probably still stay the same.

    But you are correct. It will probably break in the future. There is already an if block, as mojang moved the ChatSerializer to an inner class.

    The problem is: Is there another way to do this. And creating a package for every server version from 1.7.x to 1.11 is not great. Yes, this could be called lazy, but it overcomplicates this issue extremly.

    Sorry if this is too offtopic :/

    EDIT: To give others context to what you said @mythbusterma:
    Safeguarding Against Unchecked and Potentially Damaging Plugins
    Support multiple Minecraft versions with abstraction/maven
     
    Last edited: Oct 9, 2016
  12. Offline

    RedCoder4

    @Rayzr522 Ah ok. I will test tomorrow. @mythbusterma However, I am not thinking of that now. Ever heard of live in the present. @AlvinB Correct.
     
  13. Offline

    Rayzr522

    I will update it if they change the internals again. Easy.

    It isn't lazy, in fact it's going to a lot of extra work for the benefit of the end-users, allowing them to use it in any older version they want (back to 1.7, the earliest version that has it) and also continue to use it theoretically indefinitely. Mojang changes internals? I add another if statement. Easy.

    And as @AlvinB said, the internal classes I'm accessing haven't been changed since they made it a subclass, and I already have a check for that. The only thing I could imagine them changing is maybe adding more features to the messages (like new click actions), and that wouldn't break my code.

    Haha, but living in the present can cause serious problems in the future if you aren't careful, like if you use NMS code. That's why you use my util class instead :p
     
  14. Offline

    RedCoder4

    @Rayzr522 I will test your method when I am at my computer. With the updates there is a 7/10 of me having to update it because there are other developers on the team.
     
  15. Offline

    mythbusterma

    @Rayzr522 @RedCoder4

    Alright, as long as you're fine understanding that your plugin will break without warning at some point in the future, possibly crashing the server and providing no useful errors, yes.

    The problem is the internal code changes its method signatures without warning, possibly changing their behavior. The proper way to do it is to add a separate class for each supported version, this ensures that there are no changes that would break it.

    @AlvinB

    It will fail reliably and can be handled cleanly, however. You won't get nasty, non-descript errors because they rearranged the methods. It's really not that difficult to do it properly, and using reflection like this is deliberately circumventing the built-in safety measures that they have.


    My point is the entire point of having different names for each version is so that you don't wind up with the issues you run into when using undocumented internals that have no guarantees about whether or not they change. As long as the OP understands his code is fragile and prone to breakage for no apparent reason, that's really all I wanted to say.
     
  16. Offline

    RedCoder4

    I have added it with no problems. I am setting to solved. However, if it is okay with you I will pm you if there are any problems @Rayzr522
     
  17. Offline

    Rayzr522

    If we want to continue this line of discussion (I don't) then we should do so by PM. Just to conclude, I understand the risks fully, in this case it is highly unlikely that it will ever change, at least not for a long time.

    Also I will update it soon with safeguards so I can fail gracefully if/when it runs into problems. The thing with this is it doesn't return any data, so it won't actually screw anything up if it breaks except certain messages might not show. It's not like any data is going to get corrupted or anything like that, it will just fail quietly, notify the console, and move on.

    Reflection is not good for some thing, but in this case making a separate class per version would not only be excessive, but it would break one of the nicest features of this: it's only 1 class file, so you can just drag n' drop it in.

    Please stop being Mr. Doomsday about my code, it's highly unlikely it'll even ever break. I can't imagine they'd want to redo the chat system again.

    I want to keep this friendly so let's just leave it at that :)



    Ok! I will let you know if I update it. I will maybe try and create some sort of update checker built into it that will log to console... dunno how I'm gonna do that yet, but could be helpful.
     
  18. Offline

    blue1

    Here's an updated tutorial if anyone needs/wants it.
     
  19. Offline

    I Al Istannen

    @blue1
    That uses a different library.

    And it uses bungeecord, which is only bundled with spigot. So I wouldn't use this, if I am not sure all users will have Spigot installed.
     
  20. Offline

    blue1

    It doesn't use a library; the tutorial is on how to do this without one. It just uses Spigot, which comes from the same BuildTools that CraftBukkit does.
    It's just another bit of help for anyone who comes here later on and needs it.
     
  21. @blue1
    Well, Spigot is a library. Lots and lots of servers use CraftBukkit, not Spigot, using the Spigot libraries will break your plugin on those servers.
     
  22. Offline

    blue1

    That's true, just as craftbukkit is a library. Which makes that a mute point.
    I understand that you shouldn't use spigot libraries in a bukkit server. But in a spigot server (many people use spigot servers, even those who use bukkit forums; I am one of those), the tutorial will be of great help to anyone who needs it. Like I said, it's just for anyone who comes here and finds it useful. I'm not saying it's a God resource that works in every situation.
     
  23. Offline

    I Al Istannen

    @blue1
    I am not saying it is bad either. I am actually glad you posted an alternate approach.

    I just wanted to point out what you need to consider if you use what you did.
    The "that is another library" part was because from your comment it sounded like it is a tutorial to the beforementioned class by Rayzr.

    Your method is not universally usable as @AlvinB kindly mentioned and I have seen enough posts about errors with the bungee ChatColor, to know not everybody uses Spigot. This is just something you need to consider, nothing wrong with the API.

    Have a nice day :)
     
    blue1 likes this.
  24. Offline

    blue1

    @I Al Istannen
    Thanks for your kind reply. :) You have a nice day too.
     
  25. Offline

    Lolmewn

    I'm surprised https://github.com/mkremins/fanciful hasn't been mentioned here - it's a great library for making messages colored/clickable/have hover text and is easy to understand.
     
    blue1 likes this.
  26. Offline

    I Al Istannen

    @Lolmewn
    It is mentioned in @Rayzr522 post. I have used it before too (Item tooltip :p), and it was nice to work with.
    But Rayzr said this:
    If it still works, I would use that too (no offence ;)). Haven't checked myself though.

    EDIT: This line right here could be really annoying though.
    Code:
    Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + player.getName() + " " + jsonString);
    Pretty sure it will appear in the console log.
     
  27. Offline

    blue1

    I've used the fanciful library, but I actually found it easier and more effective to go with raw spigot (which is what the fanciful was built on). That's the tutorial I posted/made, and I actually talk about Fanciful a bit in it.
     
Thread Status:
Not open for further replies.

Share This Page