Solved More dumb questions from me (Worldedit and Basic Java)

Discussion in 'Spigot Plugin Development' started by Wilsoon, Jan 22, 2020.

Thread Status:
Not open for further replies.
  1. I'm not sure whether I can ask two questions and different codes in one thread, but I don't really wish to spam the entire forum with threads from me so I guess I'll ask together.

    1. I have a code to get a Worldedit LocalSession, but it wants a player, and I have an event to get a player that triggered the event with e.getPlayer(). I want to get the LocalSession from an onCommand but it wouldn't want a CommandSender, it wants a player. I want the player that sent the Command, how would I do it?


    Main class:
    Code (Java):
    package com.gmail.calorious.wergteleport;

    import org.bukkit.plugin.java.JavaPlugin;

    import com.sk89q.worldedit.LocalSession;
    import com.sk89q.worldedit.bukkit.WorldEditPlugin;

    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.plugin.PluginDescriptionFile;
    import org.bukkit.event.HandlerList;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerMoveEvent;


    @SuppressWarnings("unused")

    public class Main extends JavaPlugin {
        private EventHandling eventHandler;
        private Listener l;
        @Override
       public void onEnable() {
       getServer().getPluginManager().registerEvents(this.eventHandler = new EventHandling(), this); // Register Events (EventHandling.class)
       getLogger().info(ChatColor.GOLD + "Hooking to WorldEdit...");
       if(getServer().getPluginManager().getPlugin("WorldEdit") == null) {
            getLogger().info(ChatColor.RED + "Failed to hook to WorldEdit!");
            getLogger().info(ChatColor.RED + "This plugin requires WorldEdit to function.");
            getLogger().severe(ChatColor.DARK_RED + "STOPPING PLUGIN: " + getDescription().getName()); //Throws an ERROR message
            getLogger().severe(ChatColor.DARK_RED + "Reason: Dependent Plugin not found.");  //Throws an ERROR message
            getLogger().severe(ChatColor.DARK_RED + "Required Plugins: " + getDescription().getSoftDepend()); //Throws an ERROR message
            getPluginLoader().disablePlugin(this);
       }
       else {
             getLogger().info(ChatColor.GREEN + "Successfully hooked to WorldEdit!");
           }
       getLogger().info(ChatColor.GOLD + "Hooking to Worldguard...");
       if(getServer().getPluginManager().getPlugin("WorldGuard") == null) {
           getLogger().info(ChatColor.RED + "Failed to hook to Worldguard!");
           getLogger().info(ChatColor.RED + "This plugin requires Worldguard to function.");
           getLogger().severe(ChatColor.DARK_RED + "STOPPING PLUGIN: " + getDescription().getName());
           getLogger().severe(ChatColor.DARK_RED + "Reason: Dependent Plugin not found.");
           getLogger().severe(ChatColor.DARK_RED + "Required Plugins: " + getDescription().getSoftDepend());
           getPluginLoader().disablePlugin(this);
       }
        }
        @Override
        public void onDisable() {
            getLogger().info(ChatColor.DARK_RED + "[WERegionTeleport Disabled]");
            getLogger().info(ChatColor.RED + "     Plugin has disabled successfully!");
        }
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if(cmd.getName().equalsIgnoreCase("wergtp")) {
                if(args.length == 0) {
                    sender.sendMessage(ChatColor.GREEN + "WorldEdit Region Teleport");
                    sender.sendMessage(ChatColor.GREEN + "----------------------------");
                    sender.sendMessage(ChatColor.GOLD + "  /wergtp on - Enable the plugin");
                    sender.sendMessage(ChatColor.GOLD + "  /wergtp off - Disable the plugin");
                    sender.sendMessage(ChatColor.GOLD + "  /createregion (region) - Create a region for teleportation");
                    sender.sendMessage(ChatColor.GREEN + "----------------------------");
                    return true;
                }
                if(args.length == 1) {
                    if(args.toString().equals("on")) {
                        if(EventHandling.enabled) {
                            sender.sendMessage(ChatColor.RED + "FAIL: Plugin is already enabled!");
                        } else {
                            EventHandling.enabled = true;
                          sender.sendMessage(ChatColor.GREEN + "SUCCESS: Plugin has been enabled!");
                          return true;
                        }
                    if(args.toString().equals("off")) {
                        if(!(EventHandling.enabled)) {
                            sender.sendMessage(ChatColor.RED + "FAIL: Plugin is already disabled!");
                        } else {
                            EventHandling.enabled = false;
                            sender.sendMessage(ChatColor.GREEN + "SUCCESS: Plugin has been disabled!");
                            return true;
                        }
            if(cmd.getName().equalsIgnoreCase("createregion")) {
                if(args.length == 0) {
                    sender.sendMessage(ChatColor.RED + "Incorrect Usage! Usage: /createregion (regionname)");
                }
                if(args[0].length() == 1) {
                    LocalSession session = WorldEditPlugin.getSession(sender); // sender won't work because it
                }                                                                                                         // wants a Player, problem is here
            }
                        }
                    }
                }
            }
            return false;
        }
    }
     
    Event class:
    Code (Java):


    package com.gmail.calorious.wergteleport;

    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.*;

    public class EventHandling implements Listener {
        public static boolean enabled = true;
        @EventHandler
        public void onPlayerMove(PlayerMoveEvent e) {
            Player player = e.getPlayer();
            if (enabled == true) {
             
            } else {
                player.sendMessage(ChatColor.RED + "" + ChatColor.BOLD + "Entered a set region, no action. Reason: Not Enabled");
            }
        }
        public void setEnabled(boolean enabled) { EventHandling.enabled = enabled; }
    }
     
    Help?



    -----------------------
    My second part:
    This is a simple NoRain plugin I want to do which I've made a thread on, I thought the problem was fixed, but it had problems again. Although everything worked fine, only the part where I did "norain off", it returned my usage in plugin.yml, even though the rest worked. Is this because of where the "return true;" was?
    If it is, please tell me where I put it and where I should put it if I have stuff like "if" and "else".

    Main class:
    Code (Java):

    package com.gmail.calorious.Rain;

    import org.bukkit.plugin.java.JavaPlugin;

    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.weather.WeatherChangeEvent;

    public class Main extends JavaPlugin implements Listener, CommandExecutor {
        public static boolean enabled = true;
          @Override
          public void onEnable() {
              getLogger().info(ChatColor.GREEN + "                  [NO RAIN PLUGIN]                        ");
              getLogger().info(ChatColor.GREEN + "      This is a very lightweight plugin, made by Java     ");
              getServer().getPluginManager().registerEvents(this, this);
              getCommand("norain").setExecutor(this);
          }
          @Override
          public void onDisable() {
              getLogger().info(ChatColor.RED + "Plugin has been disabled successfully!");
          }
          @EventHandler
          public void onWeatherChange(WeatherChangeEvent e) {
              if(enabled = true) {
                  if(e.toWeatherState()) {
                      e.setCancelled(true);
                  }
              }
          }
          public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
              if(cmd.getName().equalsIgnoreCase("norain")) {
                  if(args.length == 0) {
                      sender.sendMessage(ChatColor.RED + "            NoRain");
                      sender.sendMessage(ChatColor.GOLD + "--------------------------------");
                      sender.sendMessage(ChatColor.GREEN + " /norain on - No Rain, foreeveerrr!");
                      sender.sendMessage(ChatColor.GREEN + " /norain off - There will be rain now.");
                      sender.sendMessage(ChatColor.GOLD + "--------------------------------");
                      return true;
                  }
                  if(args.length == 1) {
                      if(args[0].equalsIgnoreCase("on")) {
                         if(enabled) {
                            sender.sendMessage(ChatColor.RED + "Fail: Plugin is already enabled!");
                            return true;
                         } else {
                         sender.sendMessage(ChatColor.GREEN + "Success: Plugin has been enabled!");
                      }
                      if(args[0].equalsIgnoreCase("off")) {
                          if(!(enabled)) {
                              sender.sendMessage(ChatColor.RED + "Fail: Plugin is already disabled!");
                              return true;
                          } else {
                              Main.enabled = false;
                              sender.sendMessage(ChatColor.GREEN + "Success: Plugin has been disabled");
                              return true;
                          }
                      }
                      }
                  }
              }
            return false;
          }
    }
     
     
    • Optimistic Optimistic x 1
  2. 1.
    Code (Java):
    if (commandSender instanceof Player) {
        Player player = (Player) commandSender;
    }
    This is called type casting. First, you need to check wether or not the commandSender is a player (could also be a console for example) and then you can assign a player by casting the commandSender to the player.

    2. do you mean if you insert „on“?
    Because in that case you forgot to return true onece...
     
  3. Thank you for answering.
    upload_2020-1-22_18-17-53.png
    "on" worked, but "off" didnt, and I couldn't put return true because it would lead to an error "Unreachable code" dk why it's like that, hopefully someone can explain when I can use this with my example (if and else).

    EDIT: Your code for part 1 worked, but it returned this, how do I fix it?
    upload_2020-1-22_18-25-25.png
     
    #3 Wilsoon, Jan 22, 2020
    Last edited: Jan 22, 2020
  4. A return statement exits the method you're currently in. That is to say, when this statement is executed, any code that is below it will not be executed. Java prevents you from putting code directly underneath a return statement, since such code would never be executed, which is what led to your error.
     
    • Agree Agree x 1
  5. Side note, don’t name your main class main. It can cause issues later on. I recommend using the plugin name for your main class name
     

  6. Quick note - I'd put it this way:
    Code (Java):
    public void onCommand(<...>)
    {
        if (!commandSender instanceof Player) return true;
     
        Player player = (Player) commandSender;
        <code>
    }
     
    As the code will be cleaner and you won't need to put everything inside the if statement (you can't access a variable outside of the statement if you only declared it inside of the statement).

    ------------------------

    You declared your
    Code (Java):
    public static boolean enabled = true;
    as public and static. Remove the "static" part and your code should be fixed. Since the method you're trying to access is not static, you cannot make a static reference to it (you're calling it inside an if statement that checks if "enabled" is true). Also, if you don't need to access this boolean from other classes, make it "private" instead of "public". Public means it can be accessed from anywhere and it introduces bugs (/security) risks. Protected means it can only be accessed from classes in the same package, and it may be useful in some cases such as all commands reading a variable in the main class (if you don't organize your code into sub-packages, which by the way is strongly recommended). Private means only the class itself can access it. (You could create a getter and setter method, but that's something a little too advanced if you're just beginning).

    Code (Java):
    private boolean enabled = true;

    public boolean getEnabled()
    {
        return enabled;
    }

    public void setEnabled(boolean isEnabled)
    {
        enabled = isEnabled;
    }
     
    #6 mind_overflow, Jan 22, 2020
    Last edited: Jan 22, 2020
  7. Your code does not work because you forgot to close an if-statement:
    [​IMG]
    (Also please don't upload code via image but use the apposite "code" tool!)

    ------------------


    I didn't check the whole code, but if you "return false", it means the command was misused so Spigot replies with the correct usage. Change the last "return false" to "return true".

    Generally, it doesn't server much purpose to put a "return" statement at the end of every "if" statement you have, if you also use "else" statements.
    Let me make an example:

    Code (Java):
    boolean doSomething (boolean variable)
    {
        if (variable)
        {
            // Do something
            return true;
        }
        if(!variable)
        {
            // Do something else
            return true;
        }
    }
    This is generally useless as you're always returning true. Also, if you don't use "else" statements, your code will have to run checks twice as much. It will check if the first "if" is true, then it will check if the second "if" is false.
    Using "else" you can avoid this: if the first instructions set is not true, fallback to the second one:

    Code (Java):
    boolean doSomething (boolean variable)
    {
        if (variable)
        {
            // Do something
        }
        else
        {
            // Do something else
        }
        return true;
    }
    The only reason I'd put "return" inside of the if statement is if different parts of the code have to return different things:

    Code (Java):
    boolean doSomething (boolean variable)
    {
        if (variable)
        {
            // Do something
            return true; // TRUE
        }
        else
        {
            // Do something else
            return false; // FALSE
        }
    }
    If you need to check more than two conditions, then use "else if" statements instead of making new "if" ones:
    Code (Java):
    boolean doSomething (boolean variable, int x)
    {
        if (variable && x > 0)
        {
            // Do something
            return true; // TRUE
        }
        else if (variable && x <= 0)
        {
            // Do something else
        }
        else
        {
            // Do something else again
        }
        return false; // FALSE: "else if" and "if" both return false, so we're gonna leave it out as this is the only remaining possibility
    }
     
    #7 mind_overflow, Jan 22, 2020
    Last edited: Jan 22, 2020
  8. Setting attributes and methods to private is only used for organization and not for security.
     
    • Funny Funny x 1
  9. I mean, it certainly helps. If you want to bypass a private member you'd need to use reflections, or a decompiler if you want to look at the bytecode. Leaving it public makes it easily accessible by another plugin. It also depends on what do you mean by security - is it "keeping hackers out" or is it "keeping bugs out"? If I have a 30-class plugin with 10 different commands, of which every class has a public boolean named "enableCommand", it'd surely be easy to confuse one class's boolean with another class's same-name boolean.
     
  10. Security means keeping hackers out and access modifiers don’t help with that. It’s only useful to organize your code and provide some sort of consistency.
     
  11. I can't understand the return false part, and my IDE says my code doesn't have a missing bracket, instead when I put the extra bracket, it wants me to delete it.
     
  12. @Schottky Are you able to solve the issue with Worldedit?
    Code (Java):


                    Player player = (Player) sender;
                    if(sender instanceof Player) {
                    LocalSession session = WorldEditPlugin.getSession(player);
     
    Your code I did returned a "Cannot make a static reference to the non-static method getSession(Player) from the type WorldEditPlugin"
     
  13. I never wrote that code.
    Let me try to explain your error. WorldEditPlugin is defined as follows:

    Code (Java):
    class WorldEditPlugin {
        public LocalSession getSession(Player player) {...}
    }
    What you try to do is to get the session of the class WorldEditPlugin. The function, however, is defined for objects. There is a big difference here.
    What you therefore need is an object. How can you get an object? For example like this:
    Code (Java):
    WorldEditPlugin plugin = new WorldEditPlugin(...);
    Does this make sense? Obviously not; there can only be one WorldEditPlugin. In these cases, I have to admit, it's sometimes hard to see why your method wouldn't work. There is only one worldEdit; why wouldn't you, therefore, be able to resolve any methods for WorldEditPlugin?
    Well, there are a number of reasons why that doesn't work; one major reason is inheritance. You can't inherit static methods.
    Going back to your problem; how do you get the only instance (in computer science; this is called a 'Singleton' instance) of WorldEditPlugin?
    Well, luckily, WorldEdit provides a nice Method:
    Code (Java):
    final WorldEditPlugin oneAndOnlyInstance = WorldEditPlugin.getInstance();
    Notice, that you get the instance from the class itself. So, therefore, these two are somehow coupled. You can now call the method you want on that instance:
    Code (Java):
    final LocalSession session = oneAndOnlyInstance.getSession(player);
    Please note that the name oneAndOnlyInstance is just for clarity; you can name your variable that way if you want to have that clarity; but in general this name could be confusing.
     
  14. I'm not sure exactly what part you didn't understand, but I'll try explaining it with different words so you can hopefully get what I mean.
    Spigot's commands need to be put in an "onCommand" boolean method:
    Code (Java):
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {...}
    Booleans are data types that can only have a "true" or "false" value.
    This "onCommand" method is called every time something (a player, the console, a command block) sends your command in chat.
    When this method is called, all your code inside of it is run, if the specified conditions are met.
    But since this is a boolean, it always needs to return a value - whether it's true or false.
    If you write:
    Code (Java):
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
         // Some code here
         return true;
    }
    Your plugin will execute all the code you wrote inside of it, and then the boolean will become true.
    So when your Spigot server runs the command by calling the onCommand method, it will also check whether its value is true or false.
    If we make an approximation (for the sake of understanding), we can say it works this way:

    1. a player sends a command.
    2. Spigot checks which command it was, and if any plugin owns that command.
    3. If a plugin is found, the command sender, the command, the label and the args are all handed down to the plugin.
    4. The plugin does his operations using those values (so it can identify who sent the command, and what was sent)
    5. At the end of the code, the plugin makes onCommand return either "true" or "false".
    6. Spigot checks the value of the boolean onCommand.

    If the boolean is found to be true, then it's like saying to Spigot "it's alright, the command was ran succesfully.", so Spigot does not need to do anything else and moves on.
    If instead it is false, it's like warning Spigot that there was a problem running the command. So Spigot, instead of just moving on, sends the player a warning, showing him the typical usage of the command (since Spigot does not have knowledge about your particular plugin, he doesn't actually know what the problem is unless you specifically write code about that particular problem).

    So if you write "return false" at the end of your onCommand(...) method, Spigot will see the value as false and will think there was a problem running it.
     
    • Useful Useful x 1
  15. Of course your IDE does not say you have a missing bracket. If you actually had one missing, the code wouldn't compile as the compiler wouldn't be sure where the missing bracket needs to be.

    The problem is that you actually misplaced the actual bracket.
    I will try to mimick your code explaining the problem:

    Code (Java):
    boolean enabled = true;

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
    {
        if(args.length == 1)
        { // Checking if args length is 1.
            if(args[0].equalsIgnoreCase("on"))
            { // Checking if args[0] is "on".
                if(enabled)
                { // Checking if the plugin is enabled.
                    sender.sendMessage("Plugin is already enabled!");
                    return true;
                }
                else // Else, if the plugin is not enabled...
                {
                    enabled = true; // This instruction was missing! The plugin wasn't getting enabled without it
                    sender.sendMessage("Plugin has been enabled!");
                    return true;
                } // Quitting the "if(enabled)" check.
            } // Quitting the "if(args equals "on")" check.
     
            /* ^^^^^^^^^^^^^^^^^^^^^^^
            * THIS BRACKET IS MISSING!
            * You are checking if args are "off" inside the "on"
            * check, and this condition will never be met as args
            * can't be "on" and "off" at the same time.
            */

     
            else if(args[0].equalsIgnoreCase("off"))
            { // Checking if args[0] is "off".
                if(!enabled)
                { // Checking if the plugin is not enabled.
                    sender.sendMessage("Plugin is already disabled!");
                    return true;
                }
                else // Else, if the plugin is enabled....
                {
                    enabled = false; // Disable it.
                    sender.sendMessage("Plugin has been disabled!");
                    return true;
                } // Quitting the "if(!enabled)" check.
            } // Quitting the "if(args equal "off") check.
        } // Quitting the "if(args length is 1)" check.
    } // Quitting the onCommand method.
    Also, there are some modifications I'd make at your code to make it more clean and organized, but I'll move on to explaining them only once you understand this problem first, because I don't want to risk confusing you and mixing the two things.
     
    #15 mind_overflow, Jan 23, 2020
    Last edited: Jan 23, 2020
    • Friendly Friendly x 1
  16. Thank you.
    I've managed to understand these.
    I have a miscellaneous question though, is this really what I have to do in order to send messages to Console and Players?
    Code (Java):

    if(!(sender instanceof Player)) {
                getLogger().info(ChatColor.GOLD + "================================");
                getLogger().info(ChatColor.GREEN + "Server Report");
                getLogger().info(ChatColor.GREEN + "");
                getLogger().info(ChatColor.GREEN + " TPS: " + getTPS());
                getLogger().info(ChatColor.GREEN + " Uptime: " + getUpTimeSeconds());
                getLogger().info(ChatColor.GREEN + " Total Memory: " + maxMemory);
                getLogger().info(ChatColor.GREEN + " Free Memory: " + confirmFreeMem);
                getLogger().info(ChatColor.GOLD + "================================"); }
                else {
                    sender.sendMessage(ChatColor.GOLD + "================================");
                    sender.sendMessage(ChatColor.GREEN + "Server Report");
                    sender.sendMessage(ChatColor.GREEN + "");
                    sender.sendMessage(ChatColor.GREEN + " TPS: " + getTPS());
                    sender.sendMessage(ChatColor.GREEN + " Uptime: " + getUpTimeSeconds());
                    sender.sendMessage(ChatColor.GREEN + " Total Memory: " + maxMemory);
                    sender.sendMessage(ChatColor.GREEN + " Free Memory: " + confirmFreeMem);
                    sender.sendMessage(ChatColor.GOLD + "================================");
                    return true;
                }
     
    Note: This code is from another plugin I made, thus stuff like confirmFreeMem and getUpTimeSeconds() won't make sense in this code.
     
  17. Sorry that I'm blind and didn't see your post, thank you for the information, but @Stef it allowed me to put the code in the "If" section and not the "else" and sometimes it allows me to put at both. Why is that so?
    @notjacob1 I don't see how this could affect, it seems to confuse me more when I have to put my main class in plugin.yml.
     
  18. I'm on mobile right now so I won't be able to provide a detailed explanation but no, there's a much easier way.
    Do it like this:
    Code (Java):
    public boolean onCommand(CommandSender sender, ...)
    {
      sender.sendMessage("Your message goes here");
       return true;
    }
    You don't need to check if it's a player; you also don't need to use player.sendMessage("...") or getLogger().info("..."). Just use commandSender and send a message to it. This way it will get delivered to whoever sent the message, whether it's console or player.
     
    #19 mind_overflow, Jan 24, 2020
    Last edited: Jan 24, 2020
  19. Did you use WorldEdit or WorldEditPlugin?
    If you want to use WorldEdit, you get the session like this:
    Code (Java):
    WorldEdit.getInstance().getSessionManager().get(wrapPlayer(player));
    Else, you want to use the Method I have given on WorldEditPlugin
     
Thread Status:
Not open for further replies.