My plugin error

Discussion in 'Plugin Development' started by xKot, Apr 16, 2021.

  1. Offline

    xKot

    When i try to start my plugin, it crashes with this error:


    21:04:29] [Server thread/INFO]: [Kot-MegaDropTools] Enabling Kot-MegaDropTools v1.1-FOX
    [21:04:29] [Server thread/ERROR]: Error occurred while enabling Kot-MegaDropTools v1.1-FOX (Is it up to date?)
    java.lang.Error: Unresolved compilation problem:
    The method loadClass(String) in the type ClassLoader is not applicable for the arguments (Main)

    at dx.kot.tools.Main.onEnable(Main.java:130) ~[?:?]
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:263) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:351) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:480) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.craftbukkit.v1_16_R3.CraftServer.enablePlugin(CraftServer.java:494) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.craftbukkit.v1_16_R3.CraftServer.enablePlugins(CraftServer.java:408) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.craftbukkit.v1_16_R3.CraftServer.reload(CraftServer.java:881) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.Bukkit.reload(Bukkit.java:651) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:27) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.craftbukkit.v1_16_R3.CraftServer.dispatchCommand(CraftServer.java:763) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at org.bukkit.craftbukkit.v1_16_R3.CraftServer.dispatchServerCommand(CraftServer.java:748) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at net.minecraft.server.v1_16_R3.DedicatedServer.handleCommandQueue(DedicatedServer.java:387) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at net.minecraft.server.v1_16_R3.DedicatedServer.b(DedicatedServer.java:356) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at net.minecraft.server.v1_16_R3.MinecraftServer.a(MinecraftServer.java:1008) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at net.minecraft.server.v1_16_R3.MinecraftServer.w(MinecraftServer.java:847) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at net.minecraft.server.v1_16_R3.MinecraftServer.lambda$0(MinecraftServer.java:164) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_261]
     
  2. Offline

    timtower Administrator Administrator Moderator

    @xKot Post your code [code] [/code]
     
  3. Offline

    xKot

    Code:
    package dx.kot.tools;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    
    import org.bukkit.Bukkit;
    import org.bukkit.World;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.configuration.file.YamlConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.PlayerDeathEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.event.world.WorldLoadEvent;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.plugin.java.JavaPlugin;
    
    import dx.kot.tools.cmds.ChatCommand;
    import dx.kot.tools.cmds.CheckCommand;
    import dx.kot.tools.cmds.ClearCommand;
    import dx.kot.tools.cmds.CzystyCommand;
    import dx.kot.tools.cmds.DayCommand;
    import dx.kot.tools.cmds.EfektyCommand;
    import dx.kot.tools.cmds.ExtCommand;
    import dx.kot.tools.cmds.FeedCommand;
    import dx.kot.tools.cmds.FlyCommand;
    import dx.kot.tools.cmds.GamemodeCommand;
    import dx.kot.tools.cmds.GammaCommand;
    import dx.kot.tools.cmds.GodmodeCommand;
    import dx.kot.tools.cmds.GroupCommand;
    import dx.kot.tools.cmds.HealCommand;
    import dx.kot.tools.cmds.HelpopCommand;
    import dx.kot.tools.cmds.HomeCommand;
    import dx.kot.tools.cmds.KillallCommand;
    import dx.kot.tools.cmds.KotCommand;
    import dx.kot.tools.cmds.ListCommand;
    import dx.kot.tools.cmds.LiveCommand;
    import dx.kot.tools.cmds.MsgCommand;
    import dx.kot.tools.cmds.NightCommand;
    import dx.kot.tools.cmds.PomocCommand;
    import dx.kot.tools.cmds.PremiumCaseCommand;
    import dx.kot.tools.cmds.SethomeCommand;
    import dx.kot.tools.cmds.SuperKOTCommand;
    import dx.kot.tools.cmds.ThorCommand;
    import dx.kot.tools.cmds.TpDenyCommand;
    import dx.kot.tools.cmds.TpaCommand;
    import dx.kot.tools.cmds.TpacceptCommand;
    import dx.kot.tools.cmds.VanishCommand;
    import dx.kot.tools.cmds.YoutubeCommand;
    import dx.kot.tools.events.FirstJoinItems;
    import dx.kot.tools.events.onPlayerCommand;
    import dx.kot.tools.listeners.BlockPlaceListener;
    import dx.kot.tools.listeners.ClickInventoryListener;
    import net.md_5.bungee.api.ChatColor;
    
    
    
    public class Main extends JavaPlugin{
        private static Main Main;
        private static Main instance;
        public static HashMap<Player, Player> lastMessageSender; 
       
        private static Main plugin;
        private static File homesFile;
        public static YamlConfiguration homes;
        public String prefix;
        public String guiname;
        public String haseffect;
        public String havenotitem;
       
        public Main() {
            this.prefix = ChatColor.translateAlternateColorCodes('&', this.getConfig().getString("prefix"));
            this.guiname = ChatColor.translateAlternateColorCodes('&', this.getConfig().getString("namegui"));
            this.haseffect = ChatColor.translateAlternateColorCodes('&', this.getConfig().getString("haseffect"));
            this.havenotitem = ChatColor.translateAlternateColorCodes('&', this.getConfig().getString("itemmessage"));
            Main.plugin = this;
            this.homesFile = new File(this.getDataFolder(), "Homes.yml");
            this.homes = YamlConfiguration.loadConfiguration(this.homesFile);
            Main.Main = this;
        }
       
        public static Main getInstance() {
            return Main.instance;
        }
       
        public static Main getMain() {
            return Main.Main;
        }
       
        public void onEnable() {
            //blockplace jest do caseów
            Main.instance = this;
            this.getCommand("check").setExecutor((CommandExecutor) new CheckCommand());
            this.getCommand("premiumcase").setExecutor((CommandExecutor)new PremiumCaseCommand());
            this.getCommand("heal").setExecutor((CommandExecutor)new HealCommand());
            this.getCommand("feed").setExecutor((CommandExecutor)new FeedCommand());
            this.getCommand("fly").setExecutor((CommandExecutor)new FlyCommand());
            this.getCommand("ext").setExecutor((CommandExecutor)new ExtCommand());
            this.getCommand("live").setExecutor((CommandExecutor) new LiveCommand());
            this.getCommand("pomoc").setExecutor((CommandExecutor) new PomocCommand());
            this.getCommand("kot").setExecutor((CommandExecutor) new KotCommand());
            this.getCommand("superkot").setExecutor((CommandExecutor) new SuperKOTCommand());
            this.getCommand("helpop").setExecutor((CommandExecutor) new HelpopCommand());
            this.getCommand("gamma").setExecutor((CommandExecutor) new GammaCommand());
            this.getCommand("day").setExecutor((CommandExecutor) new DayCommand());
            this.getCommand("night").setExecutor((CommandExecutor) new NightCommand());
            this.getCommand("v").setExecutor((CommandExecutor) new VanishCommand());
            this.getCommand("vanish").setExecutor((CommandExecutor) new VanishCommand());
            this.getCommand("clear").setExecutor((CommandExecutor) new ClearCommand());
            this.getCommand("ci").setExecutor((CommandExecutor) new ClearCommand());
            this.getCommand("gm").setExecutor((CommandExecutor) new GamemodeCommand());
            this.getCommand("gamemode").setExecutor((CommandExecutor) new GamemodeCommand());
            this.getCommand("thor").setExecutor((CommandExecutor) new ThorCommand());
            this.getCommand("god").setExecutor((CommandExecutor) new GodmodeCommand());
            this.getCommand("godmode").setExecutor((CommandExecutor)new GodmodeCommand());
            this.getCommand("list").setExecutor((CommandExecutor)new ListCommand());
            this.getCommand("msg").setExecutor((CommandExecutor) new MsgCommand());
            this.getCommand("sethome").setExecutor((CommandExecutor)new SethomeCommand());
            this.getCommand("home").setExecutor((CommandExecutor) new HomeCommand());
            this.getCommand("yt").setExecutor((CommandExecutor)new YoutubeCommand());
            this.getCommand("youtube").setExecutor((CommandExecutor) new YoutubeCommand());
            this.getCommand("tpa").setExecutor((CommandExecutor) new TpaCommand());
            this.getCommand("tpdeny").setExecutor((CommandExecutor)new TpDenyCommand());
            this.getCommand("tpaccept").setExecutor((CommandExecutor) new TpacceptCommand());
            this.getCommand("killall").setExecutor((CommandExecutor) new KillallCommand());
            this.getCommand("check").setExecutor((CommandExecutor) new CheckCommand());     
            this.getCommand("group").setExecutor((CommandExecutor) new GroupCommand());     
            this.getCommand("czysty").setExecutor((CommandExecutor) new CzystyCommand());
            this.getConfig().options().copyDefaults(true);
            getConfig().addDefault("checker-x", "0");
            getConfig().addDefault("checker-y", "100");
            getConfig().addDefault("checker-z", "0");
            getConfig().addDefault("checked-x", "100");
            getConfig().addDefault("checked-y", "100");
            getConfig().addDefault("checked-z", "100");
            saveConfig();
            Bukkit.getPluginManager().registerEvents((Listener)new ClickInventoryListener(), (Plugin)this);
            this.getCommand("efekty").setExecutor((CommandExecutor)new EfektyCommand());
            Bukkit.getServer().getPluginManager().registerEvents((Listener)new ChatCommand(), (Plugin)this);
            this.getCommand("chat").setExecutor((CommandExecutor)new ChatCommand());
            Bukkit.getServer().getPluginManager().registerEvents((Listener)new BlockPlaceListener(), (Plugin)this);
            Bukkit.getServer().getPluginManager().registerEvents((Listener)new FirstJoinItems(), (Plugin)this);
            getServer().getPluginManager().registerEvents(new onPlayerCommand(), this);
            this.getServer().getLogger().info("Kot-Tools Loaded Successfully!");
    
           
        }
        public void onDisable() {
            this.saveHomesFile();
    }
           
        @EventHandler
        public void onDeath(final PlayerDeathEvent e) {
            e.setDeathMessage((String)null);
        }
       
        @EventHandler
        public void onJoin(final PlayerJoinEvent e) {
            e.setJoinMessage((String)null);
        }
       
        @EventHandler
        public void onQuit(final PlayerQuitEvent e) {
            e.setQuitMessage((String)null);
        }
        private void hideAdvancementsFor(final World world) {
            world.setGameRuleValue("announceAdvancements", "false");
            this.getLogger().info("Osiagniecia sa wylaczone w swiecie , '" + world.getName() + "'.");
        }
       
        @EventHandler(priority = EventPriority.MONITOR)
        public void onWorldLoad(final WorldLoadEvent event) {
            this.hideAdvancementsFor(event.getWorld());
        }
    
       
        @EventHandler
        public void onPlayerJoin(PlayerJoinEvent e) {
            Player p = e.getPlayer();
            p.sendMessage("§8§m----------------------------------------------");
            p.sendMessage("§8» §7Witaj §9" + p.getName() + " §7na §9Serwerze!");
            p.sendMessage("§8» §7Strona WWW: §9kotmc.pl");
            p.sendMessage("§8» §7Baw się dobrze!");
            p.sendMessage("§8§m----------------------------------------------");
    
        }
        public static void saveHomesFile() {
            try {
                homes.save(homesFile);
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
       
    }
     
    Last edited by a moderator: Apr 17, 2021
  4. Offline

    timtower Administrator Administrator Moderator

    @xKot Don't add constructors to your main class.
    And why are you casting almost everything?
     
  5. Offline

    xKot

    What does it mean not to add constructors? I'm new in java and i don't know how to remove constructors (if it is in my code)
     
  6. Offline

    timtower Administrator Administrator Moderator

    @xKot You made that while new with Java?
    public Main() {
    That is your constructor.
     
  7. Offline

    xKot

    I removed that constructor, and it still crashes. @timtower
     
    Last edited: Apr 17, 2021
  8. Offline

    pixelrider2000

    It says that there is an error in line 130. If I'm not wrong this is the "check" command. Maybe you could send us the CheckCommand class and the problem can be solved that way.
     
  9. Offline

    xKot

  10. Offline

    pixelrider2000

    After a quick look at the check command I couldn't spot any major flaws except the fact that you assume that "args[0]" is always a player which doesn't have to be the case and therefore could cause some errors if it ain't. But regarding your Main class I found some oddities in the way you register your commands and events. I personally do it a little differently which leads to you not having to use "this" in front of every new registration.
    I would recommend making a "private static Main plugin" in your Main class and then creating a method e.g. "public static Main getPlugin()" which returns plugin. Then you can say "plugin = this;" in your onEnable. Commands can be registered like this then "getCommand("CMD").setExecutor(new EXAMPLECMD());". That lets you remove "
    Main.instance = this;" completely. But if this doesn't work I would like to know if your plugin has worked before and if so what did you add to your plugin since then (especially to your Main class) and maybe that way you can find a solution to the problem yourself. - Sorry for being so wordy btw. ;)
     
  11. Offline

    Strahan

    Why are you making three variables for the class? That's very redundant.

    Code:
    this.prefix = ChatColor.translateAlternateColorCodes('&', this.getConfig().getString("prefix"));
    The this keyword isn't necessary. There is no method scope variable conflict. Also be aware that getString will return null if the path is invalid, so operations performed later on that var could cause an NPE. You should pass a default:
    Code:
    prefix = ChatColor.translateAlternateColorCodes('&', this.getConfig().getString("prefix", ""));
    Code:
    this.getCommand("check").setExecutor((CommandExecutor) new CheckCommand());
    No need to cast that, as timtower mentioned. CheckCommand will implement CommandExecutor, so that's superfluous.

    Code:
    this.getConfig().options().copyDefaults(true);
    getConfig().addDefault("checker-x", "0");
    getConfig().addDefault("checker-y", "100");
    getConfig().addDefault("checker-z", "0");
    getConfig().addDefault("checked-x", "100");
    getConfig().addDefault("checked-y", "100");
    getConfig().addDefault("checked-z", "100");
    saveConfig();
    IMO, it's better to just make a config.yml in the plugin with the defaults then all you gotta do is call saveDefaultConfig() in the onEnable. It's also best to do that before anything else because if you have any classes you register before that makes use of the config, your defaults won't be populated yet. Yea, you probably don't have any that do, but it's best to do things in proper order to build the habit and to account for if you change things later.

    Code:
    e.setDeathMessage((String)null);
    Why are you casting null to String? By doing that, you will be setting the death message to a literal "null" string. Ditto for the other times you do that.

    Code:
    p.sendMessage("§8§m----------------------------------------------");
    Don't embed the color character. ChatColor exists for a reason, use it so you don't hurt its feelings lol

    Code:
    Main plugin;
    You setup a plugin instance variable, but never initialize it so when the command is ran and you attempt to use it to access config, it will crash. You need to pass the main instance to the command in the constructor then set it:
    Code:
    Main class {
      onEnable {
        getCommand("whatever").setExecutor(new CheckCommand(this));
      }
    }
    
    public class CheckCommand implements CommandExecutor {
      Main plugin;
    
      public CheckCommand(Main plugin) {
        this.plugin = plugin;
      }
    Code:
    ArrayList checked = new ArrayList();
    Don't leave your List raw, type it and it should be List on the left not ArrayList per Liskov substitution principle (part of SOLID design, which being new all that is word salad that means nothing I imagine, but just know that's how it should be done). As you are using UUIDs in there, you'd want to do:
    Code:
    List<UUID> checked = new ArrayList<>();
    Code:
    Player p = (Player) sender;
    sender may not always be a Player, so you should check it first:
    Code:
    public boolean onCommand(blah blah) {
      if (!(sender instanceof Player)) {
        sender.sendMessage("Players only");
        return true;
      }
    Code:
    if(!p.hasPermission("kot.core.cmd.check")) {
        p.sendMessage("§8» §7Brakuje Ci uprawnień §8(§9kot.core.cmd.check§8)");
    } else {
    Instead of doing else, you should just return. It would prevent unnecessary indentation.

    Code:
    p1.teleport(new Location(Bukkit.getWorld("world"), x, y, z));
    You really shouldn't hardcode stuff, I'd use config to get the world name to retrieve. Then, of course, you must check when you get the World that it isn't null in case they configure an invalid world or it isn't loaded.

    If I refactor your code, including all the things I mentioned, I'd end up with:
    Code:
    public class CheckCommand implements CommandExecutor{
      Main plugin;
      List<UUID> checked = new ArrayList<>();
      
      public CheckCommand(Main plugin) {
        this.plugin = plugin;
      }
      
      @Override
      public boolean onCommand(CommandSender sender, Command cmd, String lab, String[] args) {
        if (!(sender instanceof Player)) {
          sender.sendMessage("Players only");
          return true;
        }
    
        Player p = (Player) sender;
        if (!p.hasPermission("kot.core.cmd.check")) {
          p.sendMessage(colorize("&8» &7Brakuje Ci uprawnień &8(&9kot.core.cmd.check&8)"));
          return true;
        }
    
        if (args.length == 0) {
          p.sendMessage(colorize("&9CHECK &8» &7Poprawne użycie: &9/check [nick]"));
          return true;
        }
    
        Player p1 = Bukkit.getPlayer(args[0]);
        if (pl == null) {
          p.sendMessage("Invalid player");
          return true;
        }
        if (!p1.isOnline()) return true;  // I don't think that can ever be false though
    
        World world = Bukkit.getWorld(plugin.getConfig().getString("world", "world"));
        if (world == null) {
          plugin.getLogger().warning("** An invalid world was specified in the config for command [whatever]!");
          p.sendMessage("Sorry, but an error is preventing this from working.");
          return true;
        }
    
        int x = plugin.getConfig().getInt("checker-x");
        int y = plugin.getConfig().getInt("checker-y");
        int z = plugin.getConfig().getInt("checker-z");
    
        Bukkit.broadcastMessage(colorize("&9CHECK &8» &7Gracz &9" + p1.getName() + " &7jest sprawdzany przez &9 " + p.getName()));
        p1.sendMessage(colorize("&9CHECK &8» &7Jesteś sprawdzany! Postępuj zgodnie z poleceniem administratora"));
        p1.teleport(new Location(world, x, y, z));
        p.teleport(p1);
        checked.add(p1.getUniqueId());
        return true;
      }
    
      private String colorize(String msg) {
        if (msg == null) return "";
        return ChatColor.translateAlternateColorCodes('&', msg);
      }
    }
    I don't put this here to imply you should just copy and paste it (especially since I wrote this off the top of my head and did not put it in the IDE to double check it) just to show an example.

    Nooo, don't encourage static access. While a plugin instance is actually not a bad use case for static, it's best to direct new developers to learn about dependency injection. Otherwise they come away with the idea that static = a way to ease cross class data access, when that is most assuredly not what it's for.
     
    Wick and davidclue like this.
  12. Offline

    davidclue

    @xKot and also one more thing to add to @Strahan I noticed you are registering aliases as separate commands
    Code:
    this.getCommand("gm").setExecutor((CommandExecutor) new GamemodeCommand());
    this.getCommand("gamemode").setExecutor((CommandExecutor) new GamemodeCommand());
    this.getCommand("god").setExecutor((CommandExecutor) new GodmodeCommand());
    this.getCommand("godmode").setExecutor((CommandExecutor)new GodmodeCommand());
    You do not need to do this as when you are registering commands in your yml there is an option that you can add
    Code:
    commands:
        godmode:
            usage: /godmode
            aliases: [god, anotherAliase]
    This will run the same command if they use any of its aliases.
     
    Strahan likes this.
  13. Offline

    pixelrider2000

    Nooo, don't encourage static access. While a plugin instance is actually not a bad use case for static, it's best to direct new developers to learn about dependency injection. Otherwise they come away with the idea that static = a way to ease cross class data access, when that is most assuredly not what it's for.[/QUOTE]

    Didn't think about it that way, thanks for letting me know! Although I still feel like (as you already said) that in this case it's not a bad way of doing it.
     

Share This Page