Solved Trouble with abstract commands, returns a nullpointerexception

Discussion in 'Spigot Plugin Development' started by Brocish, May 13, 2016.

  1. Hey, I have a problem when trying to abstract a command. I have a HashMap in my Main class containing all of my commands. All of the commands are registered in the constructors of the SubClasses. Could someone please explain why I'm getting a nullpointerexception? Thanks!

    Abstract class
    Code (Text):

    public abstract class BansCommand implements CommandExecutor {
        String commandName;
        String permission;
        boolean canConsoleUse;
        private Main plugin;

        public BansCommand(final String commandName, final String permission, final boolean canConsoleUse){
            this.commandName = commandName;
            this.permission = permission;
            this.canConsoleUse = canConsoleUse;
            plugin.getCommand(commandName).setExecutor(this);
            plugin.commands.put(commandName, this);
        }

        public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
            if(!plugin.commands.containsKey(commandLabel)){
                return true;
            }

            if(!sender.hasPermission(permission)){
                sender.sendMessage(colorize("&cYou do not have permission."));
                return true;
            }

            if(!canConsoleUse && !(sender instanceof Player)){
                sender.sendMessage(colorize("&cOnly players can execute this command."));
                return true;
            }

            execute(sender, args);
            return true;
        }

        public abstract void execute(final CommandSender sender, final String[] args);

        public String colorize(String message){
            return ChatColor.translateAlternateColorCodes('&', message);
        }
    }
     
    Main class
    Code (Text):

    public class Main extends JavaPlugin {

        FileConfiguration config;
        File cfile;
        FileConfiguration bans;
        File bfile;
        public static HashMap<String, BansCommand> commands;

        public void onEnable(){
            cfile = new File(getDataFolder(), "config.yml");
            config = YamlConfiguration.loadConfiguration(cfile);
            config.options().copyDefaults(true);
            save(cfile, config);
            bfile = new File(getDataFolder(), "bans.yml");
            bans = YamlConfiguration.loadConfiguration(bfile);
            bans.options().copyDefaults(true);
            save(bfile, bans);
            commands = new HashMap<String, BansCommand>();
            registerCommands();
            this.getServer().getPluginManager().registerEvents(new JoinListener(), this);
        }
        public void registerCommands(){
            new TestCommand();
        }

        public void save(File file, FileConfiguration config){
            try{
                config.save(file);
            }catch(IOException e){
                getLogger().warning("Could not save " + file.getName());
            }
        }

        public FileConfiguration getConfig(){
            return config;
        }

        public FileConfiguration getBans() {
            return bans;
        }
    }
     
    TestCommand subclass
    Code (Text):

    public class TestCommand extends BansCommand {

        public TestCommand(){
            super("test", "test.test", true);
        }

        public void execute(CommandSender sender, String[] args){
            sender.sendMessage("You ran the test command");
        }

    }
     
    Stack trace: http://pastebin.com/guZCAGbf
     
  2. MiniDigger

    Supporter

    I am not sure (I can't look at the stacktrace, pastebin is blocked at my office) but in your abstract command class, plugin never gets assigned a value and thus is null and throwing your NPE
     
  3. You've added a command to plugin.yml?
     
  4. Here is the stack trace, could you elaborate more?
    Code (Text):

    [01:59:11 ERROR]: Error occurred while enabling Bans v1.0 (Is it up to date?)
    java.lang.NullPointerException
            at com.unbinding.bans.BansCommand.<init>(BansCommand.java:22) ~[?:?]
            at com.unbinding.bans.cmds.TestCommand.<init>(TestCommand.java:12) ~[?:?]
            at com.unbinding.bans.Main.registerCommands(Main.java:40) ~[?:?]
            at com.unbinding.bans.Main.onEnable(Main.java:35) ~[?:?]
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:321) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugin(CraftServer.java:357) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.enablePlugins(CraftServer.java:317) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.reload(CraftServer.java:741) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.Bukkit.reload(Bukkit.java:535) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:25) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:641) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchServerCommand(CraftServer.java:627) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.DedicatedServer.aO(DedicatedServer.java:412) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:375) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_91]
     
     
  5. MiniDigger

    Supporter

    I was right. did you even read my post?
     
    • Like Like x 1
  6. I read your post, I'm just confused on what value to give it.
     
  7. MiniDigger

    Supporter

    you need to give it your plugin instance. I would recommend using 'dependency injection' for that.
    Add a new parameter to your BansCommand constructor so that you can give a value to 'plugin'.
    Your test command constructor needs to have that parameter too, to pass it over to super.
    Then, when you register your command, add 'this' as a paramterer to the constructor call
     
    • Agree Agree x 1
  8. Constructor from abstract class. I added the main value, how do I put it in the subcommand class for super?
    Code (Text):

    public BansCommand(Main main, final String commandName, final String permission, final boolean canConsoleUse){
        this.commandName = commandName;
        this.permission = permission;
        this.canConsoleUse = canConsoleUse;
        plugin.getCommand(commandName).setExecutor(this);
        plugin.commands.put(commandName, this);
        this.plugin = main;
    }
     
     
  9. MiniDigger

    Supporter

    you need to change the constructor there too
    Code (Text):
    public TestCommand(Main main){
            super(main,"test", "test.test", true);
        }
    then you can call it with new TestCommand(this) in your main class
     
    • Like Like x 1
  10. Thank you so much, fixed it!

    Marking as solved.