Tutorial Making a successful Bukkit plugin. #1 Player Class and Commands

Discussion in 'Resources' started by PhantomUnicorns, Feb 17, 2017.

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

    PhantomUnicorns

    General Description: Ok so I've decided to make a Bukkit tutorial series that I plan to cover pretty much anything. I plan on making one every few days and on the latest one I would like people putting comments on what to do next, and it may be featured in the next one. Here is the basic next five that I plan on doing:
    1) Player Class and Commands
    2) Events
    3) ItemStack and ItemMeta
    4) Locations and Different Block Classes
    5) Custom Plugin Idea (Please recommend below, this will pretty much be me showing how to code a plugin that is most likely common or would cover a bunch of items)

    This tutorial will pretty much cover what the title says, the Player class and Commands.

    Ok so let's start with the basic necessities, making our class and onEnable method. Because this is the basic tutorial I'm going to include pretty much all the code said, this is so beginners can pick up but don't be expecting a block of code at the bottom of all the code used.
    Code:
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin {
    
        @Override
        public void onEnable() {
      
        }
    
    }
    
    
    The @Override annotation is not required but I use it for neatness. Currently we are not going to put anything inside here, but we are going to create another function called onCommand:
    Code:
    @Override
    public boolean onCommand(CommandSender sender, Command command, String baseCommand, String[] arguments) {
    
        return true;
    }
    
    The CommandSender sender parameter is the player/console/monster that sent the command.
    The Command command parameter is the wrapper class for advance stuff for everything to do with the command and more, we won't be using this.
    The String baseCommand parameter is the letters/word right after the '/' of the command (Not including the '/' and does not matter if the player changes the key for it to another)
    The String[] arguments parameter is the blocks of letters after the baseCommand, here is an example.
    /baseCommand argument[0] argument[1] ect...

    Ok so we can do various things inside here now, test if the sender is a specific type like so:
    Code:
    if (sender instanceof Player) {
    }
    // Or
    if (sender instanceof Cow) {
    }
    // Pretty much every entity
    
    But for this tutorial I'm going to just do a general command that any type can do. To allow felixiblity I'm going to add tests to see if it is exactly the baseCommand we want and so fourth. We are going to do a heal command.
    Code:
    if (cmd.getName().equalsIgnoreCase("heal")) {
    }
    
    We use cmd.getName() because it returns the full named command (Like if they do an aliases)
    We use equalsIgnoreCase just in case the user does something like a capital H in heal or a capital E ect... Now we are going to plan our actual command (Not coding right now), we want:

    /heal --> Heal user if Player
    /heal <Player Name> --> Heal the player that was inputed
    /heal all --> Heal every Player

    Ok now that we have planned what we are going to do we need to test for zero arguments and if the sender is a Player for the first one:
    Code:
    if (cmd.getName().equalsIgnoreCase("heal")) {
      if (arguments.length == 0) {
        if (sender instaceof Player) {
        }
      }
    }
    
    Now we cast the CommandSender sender parameter to a Player variable inside all of those if statements:
    Code:
    Player player = (Player) sender;
    
    And now we heal the player:
    Code:
    player.setHealth(player.getMaxHealth());
    
    We do this instead of setting it to the highest number just in case another Plugin has edited their maxHealth.

    Now we do /heal <Player Name>. First we test for one argument then test if argument[0] is a player name and if it isn't send a message:
    Code:
    if (cmd.getName().equalsIgnoreCase("heal")) {
      if (arguments.length == 0) {
        //Code inside here
      } else if (arguments.length == 1) {
        if (Bukkit.getPlayerExact(arguments[0]) != null) {
        } else {
          sender.sendMessage("Hey yo that ain't no playa!");
        }
      }
    }
    
    Now we store it into a Player and set their health to max:
    Code:
    Player player = Bukkit.getPlayerExact(arguments[0]);
    player.setHealth(player.getMaxHealth());
    
    And finally we do /heal all:
    Code:
    if (cmd.getName().equalsIgnoreCase("heal")) {
      if (arguments.length == 0) {
        //Code inside here
      } else if (arguments.length == 1) {
        if (argument[0].equalsIgnoreCase("all")) {
        } else if (Bukkit.getPlayerExact(arguments[0]) != null) {
          //Code inside here
        } else {
          //Code inside here
        }
      }
    }
    
    And we run through all the players with a for block and set their health to max:
    Code:
    for (Player player : Bukkit.getOnlinePlayers()) {
      player.setHealth(player.getMaxHealth());
    }
    
    Now we create the plugin.yml to register it, which goes right outside the src file:
    Code:
    name: Plugin Name
    version: 1.0
    description: This is a plugin that you put on your server!
    author: PhantomUnicorns
    main: the path to your class, pm if you need help
    commands:
      Heal:
        description: Use this to heal peps!
        usage: /Heal
        aliases: [h]
    
    NOTE: I know I didn't go in depth with the Player class and I will eventually in the future, for now this is it. Please post in the comments suggestions.
    HomeWork: Make the same function but it sets their food level to max! I won't and can't check it but if you need any help with it just PM me!
     
    Last edited: Mar 4, 2017
    Jumb_1907 likes this.
  2. Offline

    Zombie_Striker

    First, you only say what you plan to do half way through the post. You should state at the top of the post what this plugin is meant to do before explaining what needs to be done. Along with this, you do not say why you are doing certain things throughout the post. In this post, and in future threads, try to tell the play what you're doing and why you're doing it.

    Now, onto some technical corrections.

    The onEnable is useless here. It does not do anything, so you don't need to mention that you have to include it.

    Monsters cannot send commands. It is only: Players, consoles, plugins, command blocks, and command minecarts. Even still, it might just be better to say "Objects".

    You may want the bullet points for this.

    CommandLabel should no longer be used. Instead, use cmd.getName() to get the name of the plugin. You want to do this because label does not support aliases, so the "h" command would not work.
     
    bwfcwalshy likes this.
  3. Offline

    AlvinB

    @Zombie_Striker @PhantomUnicorns
    Actually, entities CAN send commands! If you use the /execute command, you can have an entity execute a command, although the CommandSender won't be a direct instance of the entity, it'll be a ProxiedCommandSender and from that you can get both the player who called the command, and the entity it's being executed on.
     
    Zombie_Striker and bwfcwalshy like this.
  4. Offline

    PhantomUnicorns

    @AlvinB I personally knew that, that's why I put it :p Thanks for saying it though, also I don't understand what @Zombie_Striker means by switching CommandLabal to cmd.getName() how would this include 'h' also? I still see it only doing "heal"?
     
  5. Offline

    bwfcwalshy Retired Staff

    @PhantomUnicorns Remove the load in the plugin yaml, it is not needed and will likely just confuse people.
     
  6. Offline

    PhantomUnicorns

    @bwfcwalshy Sure I didn't really think much of it, most of my plugins have it so I just included by default.
     
  7. Offline

    AlvinB

    @PhantomUnicorns
    By using cmd.getName() instead of the label you can also support aliases. Say if you have a command "teleport" with alias "tp". If you use the label, it can either be "teleport" or "tp" depending on what the user used, but cmd.getName() will always return "teleport". Using cmd.getName() just gives you a more consistent way to check which command is being fired.
     
    Zombie_Striker likes this.
  8. Offline

    PhantomUnicorns

    Oh ok, thanks!
     
  9. Offline

    pretocki3

    @AlvinB Then If player use /teleport or /tp, cmd.getName() returns always teleport?
    I'm little bit confused.
     
  10. Offline

    AlvinB

    @pretocki3
    Yes, since teleport is the main name of the command, and tp is just an alias, cmd.getName() will return teleport.
     
  11. Offline

    pretocki3

    @AlvinB Ohhhh.... I don't even know that before. I used like if(label.equals("blah") || label.equals("blah")). Thank you!
     
  12. Offline

    PhantomUnicorns

Thread Status:
Not open for further replies.

Share This Page