Help with Scheduling a delayed task

Discussion in 'Spigot Plugin Development' started by poncethecat, May 21, 2015.

  1. gone
     
    #1 poncethecat, May 21, 2015
    Last edited: Jan 11, 2018
  2. What is the error you get in game?
     
  3. I believe the problem is that you never defined the variable 'plugin'
    Also, if this doesn't help, did you get an error in your console?
     
    • Agree Agree x 1
  4. Is there a constructor there? Otherwise it doesn't look like you initialized the "Main plugin"

    Also you are pretty daring in not performing a cast check on sender.
     
  5. Well your class isn't static but you don't have a constructor. Add a constructor and initialize your plugin object.
     

  6. I usually don't give people code, but the thing everyone is mentioning would look something like this:
    Code (Text):
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;

    public class spawnCommand implements CommandExecutor {

        public Main plugin;
        ArrayList<Player> cooldown;

    //This is a constructor, notice how it doesn't have any return type (void, String, etc) and it's name is also the same as the class.
       public spawnCommand(Main pl){
         plugin = pl;
         cooldown = new ArrayList<Player>(); //BAD!
       }

        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        Player p = (Player) sender;

        if(cmd.getName().equalsIgnoreCase("spawn")) {
            if(!cooldown.contains(p)) {
                p.teleport(p.getWorld().getSpawnLocation());
                p.sendMessage(ChatColor.DARK_RED + "Teleporting....");
                cooldown.add(p);
                Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,new Runnable(){
             
                    @Override
                    public void run() {
                        cooldown.remove(p);
                 
                    }
                }, 7L);
            }else{
                p.sendMessage("My young pattawan, you may not use this yet :3");
         
            }
     
     
            return true;
        }
            return false;
        }

    }
     
    And in your main file
    Code (Text):
    getCommand("spawn").setExecutor(new spawnCommand(this));
    Now, something you need to change is that ArrayList of Player, that's a HUGE NO NO. Why? Well, if a player logs out you still have this Player object saved, therefore it can't be garbage collected and you'll start weighing down the VM. What you need to do is keep an array list of the Players name, and then use Bukkit.getPlayer(name); when you want to do any operation involving the player.

    Something ferrybig over at Bukkit Forums said:
    Memory leaks if stored the Collection for a long time: - Player logs off: Javas GC can't remove it cause your list/set/other still contains it. So you still have the whole instance of the player (with the IP, the real name, the display name, the list name, the health, the potion effects, other plugins metadata, ...) even if minecraft tries to save it to the disc and (tries to)unloads it from ram. - Multiworld (or some other multi world plugin) unloads the world the (maybe since two or more days... but still in your list...) logged off player was in. The GC can't remove it cause there's still that player instance in your map, which is holding the world loaded, which prevents the GC from releasing RAM...

    Back to me now,
    Something else this could cause issues with is your .contains() method, because of all the information a player object contains, it could potentially not work how you want it. If there were just strings then you don't have to worry about things like a different amount of health or something causing that contains() method to not work how you expected.
     
    #6 Nateb1121, May 21, 2015
    Last edited: May 21, 2015
  7. Besides the unsafe cast. I'm not sure what the error is but here is something I'm confused about anyhow.
    Firstly #getName() is already a string so doing toString is pretty redundant. Then you keep doing Bukkit#getPlayer(name) when you can cut out the middleman and just replace that with p#teleport().

    Also what is line 33 in your class?
     
  8. Yup exactly what I thought "21.05 16:42:20 [Server] INFO Caused by: java.lang.IllegalArgumentException: Plugin cannot be null". You are not instantiating your plugin. Add the constructor as in the previous reply.
     
    • Agree Agree x 1
  9. Considering the constructor is in his class now it may also be a problem of how he instantiates it; he could be passing null in the onEnable. But overall yes plugin is null
     
  10. O shit, we keep a Player reference for a whole 7 ticks.
    Hence you do remove them on quit, it's just a PlayerQuitEvent handler away. In this case the storage is temporary - it's in the collection for 7 ticks - so that's not even required.
    Player overrides equals to only check for the name and/or UUID.
     
  11. You never assign a value to the field "plugin," hence it's still null. You need to either add "plugin = this;" at the top of onEnable (although there's probably better things that you could do), or change that line to look like
    Code (Text):

            getCommand("spawn").setExecutor(new spawnCommand(this));
     
    so that the instance of the plugin is actually getting passed in.
     
    • Like Like x 1
  12. What error? Is it the same one or something different?