Keywords in config

Discussion in 'Plugin Development' started by the_merciless, Apr 15, 2012.

  1. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Very very new to java and plugins so forgive me if this is very simple.

    I am learning from tutorials and have copied a "helloworld" plugin. But i want to change it slightly. This is the part i want to change

    if(message_lower.contains("hi") && message_lower.contains("server")){
    p.sendMessage(RED + "[server] " + WHITE + "Hello " + p.getName());
    }

    So what i want to do is, instead of the plugin looking for "hi" and "server", i want to create a config in which u can add keywords which it will look for, and an answer which it will send.

    so config would like something like this:

    Keywords: hi, server
    Answer: Hello %p

    Keywords: Where, sell
    Answer: You can sell items at the Market. Use /warp market

    and so on.

    Can anyone help me please?
  2. Offline

    r0306

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Try something like this:
    Code:
          Map<String, Integer> m = new HashMap<String, Integer>();
    @EventHandler
    public void (PlayerChatEvent event) {
    String keywords = plugin.getConfig().getString(Keywords);
    for(String keyValue : keywords.split(",")) {
      String[] words = keyValue.split(",", 2);
      m.put(words[0], words.length == 1 ? "" : pairs[1]);
    }
     
    String[] message = event.getMessage().split(" ");
    for (i = 0; i<message.length; i ++ ) {
    if (m.contains(message[i])) {
    event.getPlayer().sendMessage(plugin.getConfig().getString("Answer");
    break;
    }
    Not sure if this works as I haven't tested it yet but that's basically what you would do.
  3. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    ok, some bits in there i dont understand but will give it a try. Thanks
  4. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @the_merciless You will have to make new keyword entries for each question. For example, for your hello server option you would need "hello-server-keywords:" and "hello-server-answer".

    In your code you would need these lines of code to get each keyword and set the answer:
    Code:java
    1.  
    2. String[] keywords = plugin.getConfig().getString("hello-server-keywords").replace(" ", "").split(",");
    3. String answer = plugin.getConfig().getString("hello-server-answer");
    4. answer = answer.replace("%p", " + p.getName() + ");
    5. answer.trim();
    6. while(answer.endsWith("+")){
    7. answer.replace("" + answer.charAt((answer.length() -1)), "");
    8. answer.trim();
    9. }
    10.  


    that way you can split each keyword into it's own argument, which then you can look for and find the keyword itself. The whole bit with the while and trimming and stuff makes sure the answer is in the right format later on.

    You will need to create 2 new integers, one to reference how many arguments there are, and one to use to check which argument you're currently looking for. You'll also need a boolean to print the message once everything checks out.
    Code:java
    1.  
    2. Integer argAmount = keywords.length;
    3. Integer currentArg = 0;
    4. Boolean containsAll = true;
    5.  


    you then will need a while statement to check each argument.

    Code:java
    1.  
    2. /**this while method sets "contains all" to false if any keywords arent said*/
    3. while(currentArg <= argAmount){
    4. currentArg += 1;
    5. if(!message_lower.contains(keywords[currentArg]))
    6. containsAll = false;
    7. }
    8.  


    And finally, you need to say the message if containsAll is true
    Code:java
    1.  
    2. if(containsAll)
    3. p.sendMessage(ChatColor.RED + "[server] " + ChatColorWHITE + answer);
    4.  


    Edit: i've edited this a couple times, but it should be good now. Lol didn't mean to overshadow you @r0306. This dang 502 error spree made me not see your post before I posted :p

    This post has been edited 4 times. It was last edited by Musaddict Apr 15, 2012.
  5. Offline

    r0306

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @Musaddict
    No problem! Glad that someone else contributed as I am not entirely sure that my code works. I'm having trouble posting this right now lol.
  6. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    So the amount of Q's and A's i could have in the config would be limited to the amount entries i put in?

    This post has been edited 1 time. It was last edited by the_merciless Apr 15, 2012.
  7. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Correct (if I understand your question). Here's a test plugin I made. Turns out I needed to tweak a few things in my above post. Feel free to use this to your liking. Please note, this plugin is contained only in the main class, but I recommend making a new class with all your responses.

    Code:java
    1.  
    2.  
    3. package musaddict.serverreply;
    4.  
    5.  
    6. import java.io.File;
    7. import java.util.logging.Level;
    8. import java.util.logging.Logger;
    9.  
    10. import org.bukkit.ChatColor;
    11. import org.bukkit.entity.Player;
    12. import org.bukkit.event.EventHandler;
    13. import org.bukkit.event.EventPriority;
    14. import org.bukkit.event.Listener;
    15. import org.bukkit.event.player.PlayerChatEvent;
    16. import org.bukkit.plugin.PluginDescriptionFile;
    17. import org.bukkit.plugin.java.JavaPlugin;
    18.  
    19.  
    20.  
    21. public class ServerReply extends JavaPlugin implements Listener {
    22.  
    23. ServerReply plugin;
    24.  
    25. public static PluginDescriptionFile info;
    26. static Logger logger = Logger.getLogger("Minecraft");
    27. public static final String mainDirectory = "plugins/ServerReply";
    28.  
    29.  
    30. @Override
    31. public void onEnable() {
    32. info = getDescription();
    33. logger = Logger.getLogger("Minecraft");
    34.  
    35. Log(Level.INFO, "is enabled, version: " + info.getVersion());
    36. Log(Level.INFO, "written by [Musaddict]");
    37.  
    38. new File(mainDirectory).mkdir(); // makes the ColorKeys directory/folder in the plugins
    39. // directory if it dosen't exist.
    40.  
    41. getConfig().options().copyDefaults(true);
    42. saveConfig();
    43.  
    44. getServer().getPluginManager().registerEvents(this, this);
    45. }
    46.  
    47.  
    48. @Override
    49. public void onDisable() {
    50.  
    51. Log(Level.INFO, "was successfully disabled.");
    52. }
    53.  
    54.  
    55. public static void Log(String message) {
    56. Log(Level.INFO, message);
    57. }
    58.  
    59.  
    60. public static void Log(Level logLevel, String message) {
    61. logger.log(logLevel, "[" + info.getName() + "] " + message);
    62. }
    63.  
    64.  
    65. @EventHandler(priority = EventPriority.HIGH)
    66. public void onPlayerChat(PlayerChatEvent event) {
    67. serverHello(event);
    68. //list more methods for more responses (name them anything you want)
    69. }
    70.  
    71.  
    72. private void serverHello(PlayerChatEvent event) {
    73. Player p = event.getPlayer();
    74. String message_lower = event.getMessage().toLowerCase();
    75. String [] keywords = this.getConfig().getString("hello-server-keywords").replace(" ", "").split(",");
    76. String answer = this.getConfig().getString("hello-server-answer");
    77. Integer argAmount = keywords.length;
    78. Integer currentArg = 0;
    79. Boolean containsAll = true;
    80. answer = answer.replace("%p", p.getName());
    81. answer.trim();
    82. do {
    83. if (!message_lower.contains(keywords[currentArg]))
    84. containsAll = false;
    85. currentArg = currentArg + 1;
    86. }
    87. while (currentArg < argAmount);
    88. if (containsAll)
    89. p.sendMessage(ChatColor.RED + "[server] " + ChatColor.WHITE + answer);
    90. }
    91. }
    92.  

    Code:
    # ServerReply Configuration
    #
    # USE 4 SPACES INSTEAD OF TABS
     
    hello-server-keywords: 'hello,server'
    hello-server-answer: 'Hello %p'
    

    Code:
    name: ServerReply
    main: musaddict.serverreply.ServerReply
    version: 1.0.0 [1.2.5-R1.0]
    description: reply to messages!
    authors: [Musaddict]

    Download test plugin

    This post has been edited 2 times. It was last edited by Musaddict Apr 15, 2012.
  8. Offline

    acuddlyheadcrab

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    EDIT: I was attacked by a wild 502 error!! :O

    Well you can make a whole list in the config, and you wont have to edit code if you want to add another word. But the answer that the server gives back in the examples given will always be the same.

    Also, for convenience, this is how I would do it :)

    Code:java
    1. // Remember the imports! They're... IMPORTant!!! lolololol
    2. import java.util.List;
    3. import org.bukkit.event.player.PlayerChatEvent;
    4.  
    5. // ...
    6. public void onPlayerChat(PlayerChatEvent event){
    7. List<String> string_list = config.getStringList("PATH.TO.LIST");
    8. String msg = event.getMessage().toLowerCase();
    9.  
    10. if(containsAll(msg, string_list)){
    11. event.getPlayer().sendMessage(config.getString("PATH.TO.MESSAGE"));
    12. }
    13. }
    14.  
    15. public boolean containsAll(String string, List<String> contents){
    16. for(String content : contents){
    17. if(!string.contains(content)) return false;
    18. }
    19. return true;
    20. }


    This would reference the following config:
    Code:
    PATH:
        TO:
            LIST:
                - hi
                - server
            MESSAGE: "Sup, playa"

    This post has been edited 1 time. It was last edited by acuddlyheadcrab Apr 16, 2012.
  9. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Actually, with the method I posted, you wont have to edit the code at all if you add a word, and it also allows different responses for different keywords. For ever new response you want, you will have to copy and paste the "serverHello" method, and name it to whatever you want, then register it in the onPlayerChat method.
  10. Offline

    Sorroko

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @Musaddict, thats sill editing code. You can simply loop through the top level keys of config and then each key has a keywords item and a message item, therefore you simply add a new key in config an it shiws a new message. No need to edit plugin at all.
  11. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Wow thanks for your help guys. @Musaddict you helped alot but @ryan7745 has the idea. the whole idea of this plugin is that you can add as many questions and answers to the config as you like and the code will find it without having to edit the code each time, i thought you may be able to loop but no idea how to do it, also wanted to add a default answer if no keywords match, eg "sorry i dont have an answer to your question right now" Can you show me how i would make a loop and give a default answer?" I think i gotta watch some new tuts cos alot of this going straight over my head!

    This post has been edited 1 time. It was last edited by the_merciless Apr 15, 2012.
  12. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    i just realised that option for a default message prob doesnt make sense. let me clear it up. i will add "katie" to all the keywords questions so when the player asks a question they will only get a response if they include the word katie. essentialy they will be asking the server a question but will be calling it katie. for example "hello katie" or Katie how can i join a town" so if they dont add katie it will not respond, and if they type katie with no other keywords it will give the default answer.
  13. Offline

    Neodork

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Code:java
    1. if(args.length ==1){
    2. if(args[0].equalsignorecase("katie"))
    3. //do nothing we won't react on calling katie's name
    4. }


    Or maybe:

    Code:java
    1. if(args.length ==1 || args.length ==2){
    2. if(args.contains("katie"))
    3. //do nothing we won't react on calling katie's name
    4. }




    If this is in fact what your asking...

    This post has been edited 2 times. It was last edited by Neodork Apr 15, 2012.
  14. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @Musaddict i hope this doesnt sound stupid but couldnt u just change "hello-server-keywords" to a number, make it a variable and have it ++1 if false to serch through all questions without having to code them all?

    This post has been edited 1 time. It was last edited by the_merciless Apr 15, 2012.
  15. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    In theory it should work, but I've never done anything like that.
  16. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @the_merciless Got it working :) the new code you need is this:

    Code:java
    1.  
    2. @EventHandler(priority = EventPriority.HIGH)
    3. public void onPlayerChat(PlayerChatEvent event) {
    4. serverRespond(event);
    5. }
    6.  
    7.  
    8. private void serverRespond(PlayerChatEvent event) {
    9. Player p = event.getPlayer();
    10. String message_lower = event.getMessage().toLowerCase();
    11. Integer i = -1;
    12. for (i = 0; i < this.getConfig().getKeys(false).size(); i++) {
    13. Integer argAmount = null;
    14. String [] keywords = null;
    15. String answer = null;
    16. try {
    17. keywords = this.getConfig().getString("" + i + "k").replace(" ", "").split(",");
    18. answer = this.getConfig().getString("" + i + "a");
    19. argAmount = keywords.length;
    20. answer = answer.replace("%p", p.getName()).replace("%w", p.getWorld().getName());
    21. answer.trim();
    22. }
    23. continue;
    24. }
    25. Integer currentArg = 0;
    26. Boolean containsAll = true;
    27. do {
    28. if (!message_lower.contains(keywords[currentArg]))
    29. containsAll = false;
    30. currentArg = currentArg + 1;
    31. }
    32. while (currentArg < argAmount);
    33. if (containsAll)
    34. p.sendMessage(ChatColor.RED + "[Server] " + ChatColor.WHITE + answer);
    35. }
    36. }
    37.  


    it searches for Xk for keywords, and Xa for answers (where X is any int less than or equal to the number of entries in the config).

    This post has been edited 6 times. It was last edited by Musaddict Apr 15, 2012.
  17. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Ok so i made a new class for the responses and all looked good. exported well and no errors show up. But when running the server i get an error saying it found { and expected ; Went ovet the code again and cant spot the problem. what have i done wrong?
  18. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    oh cool, just saw your last comment after posting that ^ Still out of interest can u guess what i done wrong.
  19. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Probly did something like:
    player.sendMessage("blah"){

    idk, never seen that error before.

    Edit: Also, I realized something that would improve efficiency of the code I posted. Change this line:
    Code:java
    1.  
    2. for (i = 0; i < this.getConfig().getKeys(false).size(); i++) {
    3.  

    to this:
    Code:java
    1.  
    2. for (i = 0; i < Math.ceil(this.getConfig().getKeys(false).size()/2)+1; i++) {
    3.  

    That way it only searches for half the amount of entries (which when you think about it, there's double the number of entries to start, 1 for keywords, 1 for answers), so it still searches all of them, but it doesn't search for ones that don't exist.

    This post has been edited 3 times. It was last edited by Musaddict Apr 15, 2012.
  20. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I got it working, turned out to be a problem with the names of the package/class not sure why it gave that error tho.
    Anyway this is working PERFECTLY and i cant thank you enough for your help. Although i ended up copying your code i learnt alot from this thread, trying to work out what u guys had done and how it works etc etc. Oh 1 minor problem i got is the answer appears on screen above what they asked. Is it possible to add a 1 second delay or something?
  21. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    change the "if(containsAll){" to this:
    Code:java
    1.  
    2. if (containsAll){
    3. final String answer2 = answer;
    4. final Player p2 = p;
    5. this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
    6. public void run() {
    7. p2.sendMessage(ChatColor.RED + "[Server] " + ChatColor.WHITE + answer2);
    8. }
    9. }, 10L);
    10. }
    11.  


    the "10L" at the end is "10 ticks". 20 ticks is 1 second, so this is a 0.5 second delay. Glad to help :)

    Edited, take a second look over what I changed.

    This post has been edited 3 times. It was last edited by Musaddict Apr 16, 2012.
  22. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Can I use || in the config. For example 1k: can||could,I,be,op or Is there another way to do this.
  23. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I bet there's some way to do an OR method, but I think it would be a huge work around. At this point I think it'd be simpler to:
    1) copy and paste (with the other word)
    or
    2) include both words in the same line

    Idk tho. I've never thought to lookup strings with OR methods.
  24. Offline

    the_merciless

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    1 last thing. tried to add a reload command for when i have made changes to the config and failed miserably.

    Code:
    public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
            if(cmd.getName().equalsIgnoreCase("ask reload")){
                this.saveConfig();
                this.reloadConfig();
                sender.sendMessage(ChatColor.DARK_RED + "ASKKATIE has been reloaded");
                return true;
            }
            return false;
            }
    im not sure if saveconfig then reload config is right. The command doesnt even work.
  25. Offline

    Musaddict

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Try just reloading the config. What I think saving does is put the temporary values into the config.

    Ergo, if an option was originally FALSE (and it loaded FASLE), and you change the value manually to TRUE, then you save the config, it overwrites the TRUE back to FALSE, then loads the FALSE again, lol.

Share This Page