Solved Cancel BukkitRunnable class from another class

Discussion in 'Plugin Help/Development/Requests' started by xDeeKay, May 28, 2015.

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

    xDeeKay

    Code:
    TestRunnable testRunnable = new TestRunnable(plugin, location, inventory);
    testRunnable.runTaskLater(this.plugin, methods.timeToStart() * 20);
                               
    testRunnable.cancel();
    Is there anyway I can use testRunnable.cancel(); in another class?

    I've tried another approach by adding "spleefRunnable.setId(100);" to the above code, and using "Bukkit.getServer().getScheduler().cancelTask(100);" in the class I want to cancel the runnable from, but this doesn't seem to work. Any ideas?

    EDIT by Timtower: merged posts
     
    Last edited by a moderator: May 28, 2015
  2. Offline

    Agentleader1

    You can declare it as a public static. But if it binds to a certain player or something, you can use a HashMap.
     
  3. Offline

    xDeeKay

    @Agentleader1 I can't do this because it wants plugin, location, and inventory to become static too. I did try make an instance of the class and used "class.testRunnable.cancel();" but that brought up a NullPointerException.
     
  4. Offline

    BlackKnight625

    Humm... you could create a method on a Class like this
    Code:
    public static void cancelTestRunnable(TestRunnable testRunnable) {
    testRunnable.cancel();
    }                       
    And access it like this
    Code:
     ClassWhereYouHaveTheMethodName.cancelTestRunnable(testRunnableName); 
    This is the first time that I'm trying to help someone on the forums, so pardon me if I made a mistake :)
    Hope I could help :D
     
  5. Offline

    Agentleader1

    Code:
    public static BukkitRunnable task;
    
    public void function(){
            task = new TestRunnable(plugin, location, inventory);
            //etc.
    }
     
  6. Offline

    xDeeKay

    @BlackKnight625 Hmm, but for class.cancelTestRunnable(testRunnableName); testRunnableName still needs a local variable or field.
     
  7. Online

    timtower Ninja on the waves Moderator

    @xDeeKay Then you add a getter method?
     
  8. Offline

    xDeeKay

  9. Offline

    teej107

    To access anything from any class, you just need an instance of it. Then you can access any public member inside it. This can be easily done by passing info in the parameters of constructors or methods. If anyone tells you to make a field static so you can access it, they don't know what they are talking about and they don't know how static should be used.
     
  10. Offline

    xDeeKay

    @BlackKnight625 I've stayed clear of using any static fields. I did what @BlackKnight625 said, except I used an instance of my custom methods class. It is now methods.cancelTestRunnable(testRunnable); instead of whatever it would be as static.

    Still, I can't use cancelTestRunnable() as it requires the testRunnable, so I'm stumped. Probably not the best idea to be doing this at 2am, but I want it done.

    How I start the runnable, from a on command:
    Code:
    TestRunnable testRunnable = new TestRunnable(plugin, location, inventory);
    testRunnable.runTaskLater(this.plugin, methods.timeToStart() * 20);
    How I need to stop the runnable, from another on command class:
    Code:
    methods.cancelTestRunnable(something);
    Methods class:
    Code:
    public void cancelTestRunnable(TestRunnable testRunnable) {
    testRunnable.cancel();
    }
     
  11. Online

    timtower Ninja on the waves Moderator

    @xDeeKay You need to declare the testRunnable as a private field.
    Then you can make a getter public void something getSomething(){return testRunnable;}
    Then you can call cancel on that.
     
  12. Offline

    xDeeKay

    @timtower Declare it to the methods class simply as private SpleefRunnable spleefRunnable;?
     
  13. Online

    timtower Ninja on the waves Moderator

    @xDeeKay That would be a field, method for it would probably be
    Code:
    public SpleefRunnable getSpleefRunnable(){
      return spleefRunnable;
    }
     
  14. Offline

    xDeeKay

    @timtower I have done this too, but spleefRunnable still has no field or variable to it, since it's in the methods class and not the same class I start the runnable.
     
  15. Online

    timtower Ninja on the waves Moderator

    @xDeeKay Could you post your code then?
     
  16. Offline

    xDeeKay

    @timtower Sure thing,

    Main:
    Code:
    package bukkit.plugin.testplugin;
    
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin {
       
        public Main instance;
        public Methods methods;
       
        public void onEnable() {
            this.instance = this;
            methods = new Methods(this);
           
            this.getCommand("teststartcommand").setExecutor(new TestStartCommand(this));
            this.getCommand("teststopcommand").setExecutor(new TestStopCommand(this));
        }
    
        public void onDisable() {
        }
    }
    Methods:
    Code:
    package bukkit.plugin.testplugin;
    
    public class Methods {
    
        public Main plugin;
    
        public Methods(Main plugin) {
            this.plugin = plugin;
        }
    
        public void cancelTestRunnable(TestRunnable testRunnable) {
            testRunnable.cancel();
        }
    
        public TestRunnable getTestRunnable() {
            return testRunnable; //this is the issue
        }
    }
    TestRunnable:
    Code:
    package bukkit.plugin.testplugin;
    
    import org.bukkit.Bukkit;
    import org.bukkit.scheduler.BukkitRunnable;
    
    public class TestRunnable extends BukkitRunnable {
       
        public TestRunnable(Main plugin) {
        }
    
        @Override
        public void run() {
            Bukkit.broadcastMessage("test");
        }
    }
    TestStartCommand:
    Code:
    package bukkit.plugin.testplugin;
    
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    
    public class TestStartCommand implements CommandExecutor {
    
        public Main plugin;
    
        public TestStartCommand(Main plugin) {
            this.plugin = plugin;
        }
    
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (cmd.getName().equalsIgnoreCase("teststartcommand")) {
                TestRunnable testRunnable = new TestRunnable(plugin);
                testRunnable.runTaskLater(this.plugin, 5 * 20);
            }
            return true;
        }
    }
    TestStopCommand:
    Code:
    package bukkit.plugin.testplugin;
    
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    
    public class TestStopCommand implements CommandExecutor {
    
        public Main plugin;
        private Methods methods;
    
        public TestStopCommand(Main plugin) {
            this.plugin = plugin;
            this.methods = this.plugin.methods;
        }
    
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (cmd.getName().equalsIgnoreCase("teststopcommand")) {
                methods.cancelTestRunnable(methods.getTestRunnable());
            }
            return true;
        }
    }
     
  17. Online

    timtower Ninja on the waves Moderator

    @xDeeKay Why not make a function Main#createTestRunnable() and call that from wherever you need it?
    Then you can also cancel it as it is in Main
     
  18. Offline

    xDeeKay

    @timtower Is there any difference having it in main and having it in my methods class? I can already call it from my methods class, shouldn't it work the same way?
     
  19. Online

    timtower Ninja on the waves Moderator

    @xDeeKay It isn't important where it is located, but you should be able to cancel it. Your current code doesn't allow that as the task that is started is only a local variable.
     
  20. Offline

    xDeeKay

    @timtower Could I do the same thing with my methods class to start the runnable and then cancel it as well, or is their some significance having it in main? I only ask this because I like to keep things organised in classes rather than throwing everything in my main class.
     
  21. Online

    timtower Ninja on the waves Moderator

    @xDeeKay You need to keep a field of the task somewhere, where isn't important as long as you can use getters and setters to access it.
     
  22. Offline

    xDeeKay

    @timtower

    Code:
    package bukkit.plugin.testplugin;
    
    public class Methods {
    
        public Main plugin;
       
        public TestRunnable testRunnable = new TestRunnable(plugin);
       
        public Methods(Main plugin) {
            this.plugin = plugin;
        }
       
        public void startTestRunnable() {
            testRunnable.runTaskLater(this.plugin, 5 * 20);
        }
    
        public void cancelTestRunnable() {
            testRunnable.cancel();
        }
    
        public TestRunnable getTestRunnable() {
            return testRunnable;
        }
    }
    This works somewhat, however when I try to use startTestRunnable() twice I get this error:
    Code:
    [16:43:30] [Server thread/INFO]: xDeeKay issued server command: /teststartcommand
    [16:43:32] [Server thread/INFO]: xDeeKay issued server command: /teststopcommand
    [16:43:44] [Server thread/INFO]: xDeeKay issued server command: /teststartcommand
    [16:43:44] [Server thread/ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'teststartcommand' in plugin TestPlugin v1.0
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:140) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchCommand(CraftServer.java:625) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PlayerConnection.handleCommand(PlayerConnection.java:1058) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PlayerConnection.a(PlayerConnection.java:919) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(SourceFile:37) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(SourceFile:9) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PacketHandleTask.run(SourceFile:13) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_31]
        at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_31]
        at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:643) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:284) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:598) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:506) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_31]
    Caused by: java.lang.IllegalStateException: Already scheduled as 39
        at org.bukkit.scheduler.BukkitRunnable.checkState(BukkitRunnable.java:141) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at org.bukkit.scheduler.BukkitRunnable.runTaskLater(BukkitRunnable.java:63) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at bukkit.plugin.testplugin.Methods.startTestRunnable(Methods.java:14) ~[?:?]
        at bukkit.plugin.testplugin.TestStartCommand.onCommand(TestStartCommand.java:19) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        ... 14 more
     
  23. Online

    timtower Ninja on the waves Moderator

    Moved to Bukkit alternatives
    @xDeeKay First: the plugin that the runnable is using in its constructor is null when you create a methods object.
    Do you happen to call the same method multiple times?
     
  24. Offline

    xDeeKay

    @timtower It works the first time though, and I can cancel it fine, I just can't reschedule it. No, I'm only calling the method once:

    Code:
    package bukkit.plugin.testplugin;
    
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    
    public class TestStartCommand implements CommandExecutor {
    
        public Main plugin;
        private Methods methods;
    
        public TestStartCommand(Main plugin) {
            this.plugin = plugin;
            this.methods = this.plugin.methods;
        }
    
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (cmd.getName().equalsIgnoreCase("teststartcommand")) {
                methods.startTestRunnable();
            }
            return true;
        }
    }
     
  25. Online

    timtower Ninja on the waves Moderator

    @xDeeKay Might need to recreate it for that purpose.
     
  26. Offline

    xDeeKay

  27. Online

    timtower Ninja on the waves Moderator

    @xDeeKay Setting the field again with a new object.
     
  28. Offline

    xDeeKay

    @timtower But shouldn't I only need to set it once and then be able to start and stop it as much as I like? Can you give me an example of what you mean?

    Edit: I think I get it,
    Code:
    testRunnable.runTaskLater(this.plugin, 5 * 20);
    has become:
    Code:
    Bukkit.getScheduler().runTaskLater(this.plugin, new TestRunnable(plugin), 5 * 20);
    Now I can't seem to cancel it:
    Code:
    [17:44:11] [Server thread/INFO]: xDeeKay issued server command: /teststartcommand
    [17:44:15] [Server thread/INFO]: xDeeKay issued server command: /teststopcommand
    [17:44:15] [Server thread/ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'teststopcommand' in plugin TestPlugin v1.0
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:140) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchCommand(CraftServer.java:625) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PlayerConnection.handleCommand(PlayerConnection.java:1058) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PlayerConnection.a(PlayerConnection.java:919) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(SourceFile:37) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(SourceFile:9) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.PacketHandleTask.run(SourceFile:13) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_31]
        at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_31]
        at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:643) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:284) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:598) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:506) [craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_31]
    Caused by: java.lang.IllegalStateException: Not scheduled yet
        at org.bukkit.scheduler.BukkitRunnable.getTaskId(BukkitRunnable.java:134) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at org.bukkit.scheduler.BukkitRunnable.cancel(BukkitRunnable.java:18) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        at bukkit.plugin.testplugin.Methods.cancelTestRunnable(Methods.java:22) ~[?:?]
        at bukkit.plugin.testplugin.TestStopCommand.onCommand(TestStopCommand.java:19) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit-1.8-R0.1-SNAPSHOT.jar:git-Bukkit-bbf72f3]
        ... 14 more
    Is this because the scheduler hasn't run the BukkitRunnable yet, so therefor the cancel method has nothing to cancel because the BukkitRunnable technically hasn't scheduled a task?
     
    Last edited: May 29, 2015
  29. Online

    timtower Ninja on the waves Moderator

    @xDeeKay I generally keep my tasks running all the time. And you shouldn't even need to cancel this task as it only runs once.
     
  30. Offline

    xDeeKay

    @timtower I understand, but in my case I do need a method to be able to cancel it because at one point I will have a BukkitRunnable counting down from 1 minute, and I will need to be able to cancel it and run it instantly, like a "force start" feature, if you get what I mean.
     
Thread Status:
Not open for further replies.

Share This Page