Solved LAST STEP OF PRE-DEVELOPMENT: My 1st plugin

Discussion in 'Spigot Plugin Development' started by NamerPRO, Jul 2, 2018.

  1. So I had already add a lot of cool features to my plugin, but there are 2 questions I'd like you to answer me.

    1st question:
    I try to create 2 commands.
    /sh and /sh reload. What I've done:

    Java:
    Code (Java):
    @Override
        public void onEnable() {
            //SOMETHING
            this.getCommand("sh").setExecutor(this);
            this.getCommand("sh reload").setExecutor(this);
           //SOMETHING
       }
     
    Code (Java):
    @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if ((cmd.getName().equalsIgnoreCase("sh"))) {
                  if(args[0] == "reload") {
                      if ((sender instanceof Player)) {
                          reloadConfig();
                          Player p = (Player)sender;
                          p.sendMessage("§7[§fServer§6HELP§7]§8: §aReload complete!");
                      } else {
                          reloadConfig();
                          Bukkit.getConsoleSender().sendMessage("§7[§fServer§6HELP§7]§8: §aReload complete!");
                      }
                      return true;
                  } else {
                      if ((sender instanceof Player)) {
                          Player p = (Player)sender;
                          p.sendMessage("§fServerHELP! §6Help §71/1:");
                          p.sendMessage("§7§m-------------------");
                          p.sendMessage("§f§l/sh §r§7-§e shows this page");
                          p.sendMessage("§f§l/sh reload §r§7-§e reloads config.");
                          p.sendMessage("§7§m-------------------");
                      } else {
                          Bukkit.getConsoleSender().sendMessage("§fServerHELP! §6Help §71/1:");
                          Bukkit.getConsoleSender().sendMessage("§f/sh §r§7-§e shows this page");
                          Bukkit.getConsoleSender().sendMessage("§f/sh reload §r§7-§e reloads config.");
                      }
                      return true;
                  }
            }
            return false;
        }
    Plugin.yml:
    Code (YAML):
    name: xxx
    main
    : xxx
    author
    : NamerPRO
    version
    : xxx
    description
    : xxx
    commands
    :
       sh
    :
          description
    : plugin help page
          usage
    : /sh
       sh reload
    :
          description
    : reloads the plugin
          usage
    : /sh reload
    ERROR:
    Code (Text):
    [18:39:05 ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'sh' in plugin ServerHELP v1.0.0
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:140) ~[craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:620) ~[craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.PlayerConnection.handleCommand(PlayerConnection.java:1106) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:966) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.PacketPlayInChat.a(SourceFile:37) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.PacketPlayInChat.a(SourceFile:9) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_171]
            at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_171]
            at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:673) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:335) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:629) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:537) [craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_171]
    Caused by: java.lang.ArrayIndexOutOfBoundsException: 0
            at ru.namerpro.serverhelp.mainListener.onCommand(mainListener.java:202) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit-1.8.8-R0.1-SNAPSHOT-latest.jar:git-Bukkit-18fbb24]
            ... 15 more
    2nd question:
    \n doesn't work in messages. When I tried it firstly it worked, then (after too many ctrl z ago (now)) it doesn't work :( Help wanted :)

    Parts of code:
    Code (Java):
    String messageToPlayer = getConfig().getString("MessageToPlayer");

    String message = ChatColor.translateAlternateColorCodes('&', messageToPlayer);

    p.sendMessage(message);
    In config had:
    Code (YAML):
    MessageToPlayer: |-
        &f&m----------\n
        &r&6{PLAYER}!\n
        &fWelcome to &7{WORLD}\n
        &aGood Luck))\n&f&m----------'
    -|
    Now have:
    Code (YAML):
    MessageToPlayer: '&f&m----------\n&r&6{PLAYER}!\n&fWelcome to &7{WORLD}\n&aGood Luck))\n&f&m----------'

    BONUS QUESTION FOR VISITORS OF THIS THREAD:
    How to create variables?
     
  2. I want {PLAYER} to show player's name.
     
  3. For the 1st Question,
    You can clearly see the error and if memory serves, that happens when you try to access an array with an index greater than its size.
    Over here that array is args[]
    When you do /command, you provide no arguments, so the size of args[] is 0 but still you are trying to access args[0], thus, the exception. (To remove this error, add a check before accessing args[0] to see if the length of args is greater than 0 or not)

    For the 2nd Question,
    Did you mean that \n is not working when you send a message to a player including "\n" or did you mean something with the config?

    For the Bonus Question,
    Just replace the String you get from the config.
    Code (Text):

    String msg = getConfig().getString("xxx");
    msg.replace("{PLAYER}", <value as String>);
     
    #3 CyberCrafter, Jul 2, 2018
    Last edited: Jul 2, 2018
    • Like Like x 1
  4. For question 1.
    sh and sh reload are not two separate commands. You only need to declare sh and treat reload as an argument (as you already do in your code).
    In general, string comparison should be done with .equals (or .equalsIgnoreCase) not ==. There are some nuances that this is the case, but generally better to use .equals for objects.
    The array index out of bounds exception happens because you did /sh and just started to compare to reload. if arguments are empty (nothing after /sh) then it can't get the first element of the args array (i.e there is no args[0]).
    Another aside, don't explicitly use the section symbol. Either use ChatColor.WHATEVER or \u00A7. The former especially because if Mojang decide for whatever reason to switch the symbol (as they did from & to section) then you would not need to change anything yourself as it will be done by Spigot devs. The latter because if it is reopened in unicode 8 (I believe this is most used in IDEs) then it may show as an invalid character (or ? symbol) invalidating the plugin when trying to recompile it.

    For question 2.
    Easiest fix would be to send as string list rather than string, making each line a new line. So would look like:
    Code (Text):
    MessageToPlayer:
        - '|-&f&m----------'
        - '&r&6{PLAYER}!'
        - '&fWelcome to &7{WORLD}'
        - '&aGood Luck))\n&f&m-----------|'
    And could be gotten with getConfig().getStringList("MessageToPlayer");
     
    • Like Like x 1
  5. 1) "reload" is actually an argument for the command, not part of the command. Look here for an example on how to handle this.

    2) The API does not handle new lines for you. You can construct your own method to handle these and use it throughout your code.

    Bonus) Use String#replace() to handle that for you, as seen here.
     
    • Winner Winner x 1
    • Informative Informative x 1
  6. 3/3

    you won you can get your price at akk.li/pics/anne.jpg
     
    • Funny Funny x 1
  7. QUESTION 1 SOLVED!
    p.s: Do I have to add /sh reload to plugin.yml?
    I added it as:
    Code (YAML):
    sh reload:
          description
    : reloads the plugin
          usage
    : /sh reload
    Solution of question 1:
    Code (Java):
    @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if ((cmd.getName().equalsIgnoreCase("sh"))) {
                if(args.length == 0) {
                    if(sender.hasPermission("serverhelp.help") || sender.hasPermission("serverhelp.*")) {
                        if (sender instanceof Player) {
                            Player p = (Player)sender;
                            p.sendMessage("§fServerHELP! §6Help §71/1:");
                            p.sendMessage("§7§m-------------------");
                            p.sendMessage("§f§l/sh §r§7-§e shows this page");
                            p.sendMessage("§f§l/sh reload §r§7-§e reloads config.");
                            p.sendMessage("§7§m-------------------");
                        } else {
                            Bukkit.getConsoleSender().sendMessage("§fServerHELP! §6Help §71/1:");
                            Bukkit.getConsoleSender().sendMessage("§f/sh §r§7-§e shows this page");
                            Bukkit.getConsoleSender().sendMessage("§f/sh reload §r§7-§e reloads config.");
                        }
                        return true;
                    } else {
                        Player p = (Player)sender;
                        p.sendMessage("§7[§fServer§6HELP§7]§8: §cYou don't have enough permissions!");
                        return true;
                    }
                } else if(args.length == 1 && args[0].equalsIgnoreCase("reload")) {
                    if(sender.hasPermission("serverhelp.reload") || sender.hasPermission("serverhelp.*")) {
                        reloadConfig();
                        if(sender instanceof Player) {
                            Player p = (Player)sender;
                            p.sendMessage("§7[§fServer§6HELP§7]§8: §aReload complete!");
                        } else {
                            Bukkit.getConsoleSender().sendMessage("§7[§fServer§6HELP§7]§8: §aReload complete!");
                        }
                        return true;
                    } else {
                        Player p = (Player)sender;
                        p.sendMessage("§7[§fServer§6HELP§7]§8: §cYou don't have enough permissions!");
                        return true;
                    }
                } else {
                    if (sender instanceof Player) {
                          Player p = (Player)sender;
                          p.sendMessage("§7[§fServer§6HELP§7]§8: §cUnknown command! §7Use §8/sh §7for more information!");
                    } else {
                        Bukkit.getConsoleSender().sendMessage("§7[§fServer§6HELP§7]§8: §cUnknown command! §7Use §8/sh §7for more information!");
                    }
                    return true;
                }
            }
            return false;
        }
     
  8. No, you only need the base command "sh" to be defined in your plugin.yml
     
  9. What should be the description?
    Is it fine if I'll make it like this:
    Code (YAML):
    sh:
          description
    : main command of the plugin with two actions one of which shows a help page and another one allows to reload config.yml
          usage
    : /sh <argument>
    Are there any special rules of making this descriptions.
     
  10. Think of yourself as the user who'll use the plugin. If you didn't know what a command did and looked at the description, what would be an useful message for you? Remember that as the plugin creator you of course know exactly how everything works, whereas the end user probably has no clue as he's looking for help. So, set it to something that you would find helpful.
     
    • Agree Agree x 1
  11. QUESTION 2 SOLVED!

    Solution of question 2:
    Code (Java):
    List<String> messageToPlayer = getConfig().getStringList("MessageToPlayer");

    //Some code here...

    for(int i = 0; i < messageToPlayer.size(); i++) {
                            String message = messageToPlayer.get(i);
                            p.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
    }

     
    #11 NamerPRO, Jul 4, 2018
    Last edited: Jul 4, 2018
  12. Bonus question solved!

    Solution of bonus question:

    Code (Java):
    p.sendMessage(ChatColor.translateAlternateColorCodes('&', message.replace("{PLAYER}", p.getName()).replace("{WORLD}", p.getWorld().getName()).replace("{DISPLAYNAME}", p.getDisplayName())));
     
  13. Pretty sure this was all solved 2 days ago when I gave you the answers ^_^

    [​IMG]
     
  14. Well, you were wrong here.

    1) I understood by myself that "reload" is actually an argument for the command, not part of the command.
    2) I used a @nikmanG's idea of \n solution
    3) I thought that your links in 2) are same and didn't look the 2th xD

    Sorry, if I made you upset. Anyway, thank you for believing in my strengthens.

    BUT!
    You can still become VERY useful if you say me how to create config with comments (without internet, because I'd already read all of those postings)!
     
  15. FrostedSnowman

    Resource Staff

    billy is very upset. do not upset billy
     
    • Like Like x 1
    • Agree Agree x 1
    • Funny Funny x 1
    • Winner Winner x 1
  16. FrostedSnowman

    Resource Staff

    create your config in your bundled resources in your project, basically set it up there with comments and anything else you may need. then call
    JavaPlugin#saveDefaultConfig in your onEnable or similar
     
  17. I was hoping I won since I answered all 3 things in what I thought was great detail. Even had links to working code for each of his questions.

    Maybe I'll get the giant stuffed animal next time. :( :( :(

    [​IMG]
     
    • Like Like x 1
    • Winner Winner x 1
  18. Don't worry))) I will give you an informative mark.
     
    • Friendly Friendly x 1
  19. Now you can be happy :)
     
    • Like Like x 1