Solved Have scheduler task cancel itself?

Discussion in 'Plugin Development' started by skore87, Jan 7, 2012.

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

    skore87

    I have a scheduler to continually check the velocity of a TNT entity that I spawn. I intend to do my execution when it reaches 0 and at the same time cancel the current task. Is there any way to get the ID of the task from within itself?
     
  2. I think that scheduler tasks which only run once such as delayed tasks cancel themselves but to make sure you should do the following.

    Assign the scheduler task an integer value, the Bukkit.getServer().getScheduler.scheduleSomeTask() returns an int of the id of that task you can then use that to cancel the task at a later time.

    Code:java
    1.  
    2. int taskid = Bukkit.getServer().getScheduler().scheduleAsyncRepeatingTask(snip){};
    3. Bukkit.getServer().getScheduler().cancelTask(taskid);
    4.  
     
  3. Offline

    skore87

    Well yes, but... in my situation this wouldn't work. What I somehow need to do, is get the ID of itself from itself.
    Code:java
    1. Integer taskID = Bukkit.getScheduler().scheduleAsyncRepeatingTask(Bukkit.getPluginManager().getPlugin("TNTCannon"), new Runnable(){
    2.  
    3. @Override
    4. public void run() {
    5. // if statement, then cancel taskID
    6. }
    7.  
    8. }, 10L, 5L);


    The only thing I can think of is doing a Future task... I'll try that. Idk.. I'm lost...

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  4. Nope. You would just define the variable in your class not the loop so then you can access it from anywhere.

    Eg:

    Code:java
    1.  
    2.  
    3. private int taskId;
    4.  
    5. public void startScheduler(){
    6. this.id = Bukkit.getServer.getScheduler.scheduleSomeTask(Plugin, new Runnable(){
    7. public void run(){
    8.  
    9. }
    10. }, 20L delay, 20L repeat);
    11. }
    12.  
    13. public void stopScheduler(){
    14. Bukkit.getServer().getScheduler().cancelTask(this.taskId);
    15. }
    16.  
     
  5. Offline

    knightidus

    or you could pass the canceling in to another method and call it after you have delayed or whatever, like this:
    Code:
    public void stopScheduler(int i){
        Bukkit.getServer().getScheduler().cancelTask(i);
    }
     
  6. Or make a whole different class
    Code:java
    1.  
    2. private static class SchedulerTask implements Runnable {
    3. private int id;
    4. public int getId() {
    5. return id;
    6. }
    7. public void setId(int id) {
    8. this.id = id;
    9. }
    10. @Override
    11. public void run() {
    12. // Do whatever
    13. Bukkit.getScheduler().cancelTask(taskId);
    14. }
    15. }
    16.  

    Then to call it
    Code:java
    1.  
    2. SchedulerTask task = new SchedulerTask();
    3. task.setId(Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, task, 10, 10));
     
    L3N, Ne0nx3r0 and skore87 like this.
  7. Offline

    ZNickq

    No, his problem is he can't cancel it from itself! I do have a fix though! Have a new class which implements runnable, and in that class, have a method like this:
    Code:java
    1.  
    2. private int id;
    3. public void setTaskId(int id) {
    4. this.id=id;
    5. }
    6. private void cancel() {
    7. Bukkit.getScheduler().cancelTask(id);
    8. }
    9.  

    So you create a new instance if this class (RunnableClass rc = new RunnableClass), create the scheduled task, get the id from it, and then do rc.setTaskId(taskid); ^.^


    LE: Ninja'd by @tips48
     
    L3N, FunnyGopher and skore87 like this.
  8. Offline

    skore87

    @tips48 and @ZNickq

    Exactly what I was looking for! I'm mad that I didn't think about it, lol.
     
  9. ZNickq likes this.
  10. Offline

    the_merciless

    I know this is old but wouldnt this be easier.

    Code:
    public class Main extends JavaPlugin implements Listener {
     
    int task1;
    int timer = 30;
     
    public void starttimer() {
            task1 = getServer().getScheduler().scheduleSyncRepeatingTask((Plugin) this, new Runnable() {
               
                @Override
                public void run(){
                   
                   //do stuff
       
                    }
       
                if ( timer = 0){
                        Bukkit.getScheduler().cancelTask(task1);
                    }
                    timer--;
            },0L, 20L);
        }
    
     
  11. Offline

    bobacadodl

    You cant refer to non-final variables from within a runnable??
     
  12. Offline

    the_merciless

    Oh yeah so make it final. I know it works as I used it several times.
     
  13. bobacadodl
    He's using a field, so it will work.

    the_merciless
    No need for final since you're using a field...

    But it would be easier to just use BukkitRunnable:
    Code:
    new BukkitRunnable()
    {
        public void run()
        {
            cancel();
        }
    }.run...(...);
    You can also do that form another class by extending BukkitRunnable, then you can just use run*() and cancel() methods in the class.
     
    joserobjr and bobacadodl like this.
  14. Offline

    skore87

    Bit of a necro guys XD. But anyway, when I made this thread there wasn't the BukkitRunnable class. And the way that the_merciless suggests wouldn't work because the value isn't set yet and that it isn't a final.
     
  15. skore87
    It's a field, so it does work, no need for final.
    Also the value is not set at the time the class is initialized but it will be set at the time when it needs to be canceled.

    Try it yourself with debug messages, you'll see.
     
  16. Offline

    LazyLemons

    Or you could just store the taskID in a HashMap and do :
    Code:
    Bukkit.getScheduler().cancelTask(hashmap.get("taskID"));
    
     
  17. LazyLemons
    Same thing only less efficient... some might also say it's pointlessly complicated :p
     
  18. Offline

    LazyLemons

    Code:
    hashmap.put("tastID",  Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
    
    Not really complicated.
     
  19. Offline

    the_merciless

    Yeah BukkitRunnable is fairly new, i learnt to do it this way a long time ago, and i have done it this way many times since, so yes it does work.

    I actually came here to find an answer to a different question. Maybe you guys can help me out.

    What i'm trying to do is have a repeating task start each time a player does something, and then cancel the task after an amount of time which will differ between players. For this reason I have to have a task id for each task. How can i set a different task id for each task? Hope that makes sense.

    As an example, lets say when a player eats a golden apple he is given god mode then i start a repeating task as a countdown. when the countdown reaches 0 I need to take away god mode and cancel the task. Since more than one player may be counting down they will each need a different task id.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  20. Use BukkitRunnable and you can cancel the task inside it without needing to store it.
     
  21. Offline

    the_merciless

    Oh yeah, we already been over that. I'm just used to doing it the old way
     
  22. Offline

    skore87

    I have in the past. It will not have the value you're expecting.
     
  23. skore87
    Your old test was wrong then, you should've re-tested it.
    test code & result (open)

    Code:
        int taskId = 0;
        
        @Override
        public void onEnable()
        {
            taskId = getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable()
            {
                int timer = 5;
                
                @Override
                public void run()
                {
                    if(timer > 0)
                    {
                        System.out.print("[debug] timer = " + timer + " | taskId = " + taskId);
                    }
                    else
                    {
                        System.out.print("[debug] Done! | taskId = " + taskId);
                        
                        Bukkit.getScheduler().cancelTask(taskId);
                    }
                    
                    timer--;
                }
            }, 0L, 20L);
        }
    Result:
    As you can see, taskId is not 0 because when run() is executed the taskId is asigned... if it weren't asigned then it would mean the thread froze there which means that the server froze.


    But like I said, easier to just use BukkitRunnable :p
     
  24. Offline

    skore87

    .... the variable will not have a value until the method completes... and because the method includes the anonymous class, it will not have a value... thus you will not have the value you're looking for.

    and i had done that sort of thing in the past, but there is a possibility they changed it with future classes. who knows..
     
  25. skore87
    The method completes when it registers the task, calling run() is not part of that same call so value asignment does not depend on it, therefore the value is asigned when run() is called because it's called by something else.

    If you were to:
    Code:
    int taskId = 0;
        
        @Override
        public void onEnable()
        {
            taskId = getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable()
            {
                private int id = taskId; // this will NOT work because taskId is 0 at this point, until the class is fully read.
                void run()
                {
                     // ...
                }
            }
       }
    Then it would be invalid, I get it :p
     
  26. Offline

    skore87

    ... i didn't use private like that...
     
Thread Status:
Not open for further replies.

Share This Page