Solved Repeat a task for a period of time or X times.

Discussion in 'Spigot Plugin Development' started by AlonsoAliaga, Mar 7, 2018.

Thread Status:
Not open for further replies.
  1. As the title says. I need to repeat a task for a period of times or X times before it stops itself.
    I tried:
    Code (Text):
    Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Plugin plugin, new BukkitRunnable() {

    public void run() {
            p.sendMessage("REPEAT MESSAGE");
        }
    }, 60L, 20L)
    Which means the first message is sent after 60L (3 seconds) and time between 2nd, 3nd and so on would be 20L (1 second) but what i need is that the task stops after "X" L or after X times that task is repeated.

    Any help?
     
  2. Just add a variable out of the run method that increase each time the run method is called. And when it reaches your X times, cancel() it and return.
     
  3. Code (Text):
            Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Plugin plugin, new BukkitRunnable() {
                int i = 0;
                public void run() {
                    i++;
                        p.sendMessage("REPEAT MESSAGE");
                        if(i == 5) {
                            this.cancel();
                        }
                    }
                }, 60L, 20L);
    use smth like this
     
  4. Code (Java):

    final long startTime = 60;
    final long repeatTime = 20;
    final long cancelTime = 100;
     final int yourTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Plugin plugin, new BukkitRunnable() {
                public void run() {
                 // Your code
                    }
                }, startTime, repeatTime);

    Bukkit.getServer().getScheduler().scheduleDelayedTask(Plugin plugin, new BukkitRunnable() {
                public void run() {
             Bukkit.getScheduler.cancelTask(yourTask);
                    }
                }, startTime + repeatTime + cancelTime);
     
    You could also do it this way. There many ways of doing this. I'm simply giving you an example.
     
  5. For me, i use bukkitrunnable, then putting methods inside it, and then make the bukkitrunnable to run every X ticks.
     
  6. Thanks everyone!
    I used @TheNickSkater, repeteating task works but it doesnt stop.
    Just keep spamming the message and when it reachs the maximun time, console gets an error.

    Code (Text):
    [Plugin] Task #1840 for PLUGIN v1.0-SNAPSHOT generated an exception
    java.lang.IllegalStateException: Not scheduled yet
            at org.bukkit.scheduler.BukkitRunnable.getTaskId(BukkitRunnable.java:134) ~[server.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.scheduler.BukkitRunnable.cancel(BukkitRunnable.java:18) ~[server.jar:git-Spigot-db6de12-18fbb24]
            at com.alonsoaliaga.plugin.Events$1.run(Events.java:79) ~[?:?]
            at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftTask.run(CraftTask.java:71) ~[server.jar:git-Spigot-db6de12-18fbb24]
            at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:350) [server.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:723) [server.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374) [server.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [server.jar:git-Spigot-db6de12-18fbb24]
            at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [server.jar:git-Spigot-db6de12-18fbb24]
            at java.base/java.lang.Thread.run(Unknown Source) [?:?]
    Not scheduled yet?
     
  7. Can we see the updated code?
     
  8. Try setting
    Code (Text):
     int i = 0;
    outside the bukkit runnable
     
  9. Code (Text):
    Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(instance, new BukkitRunnable() {
                            int i = 0;
                            @Override
                            public void run() {
                                i++;
                                p.sendMessage("REPEAT MESSAGE");
                                if(i == 5) {
                                    this.cancel();
                                    return;
                                }
                            }
                        }, 100L, 10L);
    After @marcangeloh suggestion

    Code (Text):
    int i = 0;
                        Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(instance, new BukkitRunnable() {
                            @Override
                            public void run() {
                                i++;
                                p.sendMessage("REPEAT MESSAGE");
                                if(i == 5) {
                                    this.cancel();
                                    return;
                                }
                            }
                        }, 100L, 10L);
    Says it must be final, when i usa final, i++ error

    EDIT: What i want is for example, blocks above a location keep replacing for AIR until there is no blocks above, thats when the task stop. Any suggestion?
     
  10. #1 You did not make that int final #2 That question is irrelevant to the original question that you created for this thread.
     
  11. The exception you get is one my pet peeve with Bukkit's Scheduler.

    This code will exception:
    Code (Text):
    Bukkit.getScheduler().runTaskTimer(PLUGIN_INSTANCE, () -> {
        cancel();
    ), 0L, 20L);
    This code works as expected:
    Code (Text):
    new BukkitRunnable() {
        public void run() {
            cancel();
        }
    }.runTaskTimer(PLUGIN_INSTANCE, 0L, 20L);
    Regarding your problem with "final", do read up about lambdas and effectively final.
    But for the sake of helping, you would put the counter variable (i) inside the anonymous class's scope.
    Like so:
    Code (Text):
    new BukkitRunnable() {
        private int i = 0;
        public void run() {
            if(i >= 5) {
                cancel();
            }
            ++i;
            Bukkit.broadcastMessage("Second " + i);
        }
    }.runTaskTimer(PLUGIN_INSTANCE, 0L, 20L);
     
  12. Though the question of @CoKoC is correct and will very most likely fix your issue, I can also advise to make a class that extends the BukkitRunnable class so that you can keep your code a bit more organized and reusable, and so you can easily just call your own class straight away. It works exactly the same as you currently are doing it, the only difference is that the class would no longer be anonymous. Do make sure you pass on any additional parameters in the constructor of this new class if you need them (such as a player object or a reference to your main JavaPlugin instance).

    The end result would look something like this:
    Code (Java):
    Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(instance, new CustomRunnable(plugin, player), 0L, 20L);
    This is however optional, you can choose to take a look at it or ignore it depending on your use case, up to you.
     
  13. Thanks everyone, i could get it working with @CoKoC code. I'll read so i can learn more.
    About my other question the only option i could find is using this code:
    Code (Text):
                        new BukkitRunnable() {
                            private int i = 0;
                            @Override
                            public void run() {
                                if(i >= 40) {
                                    cancel();
                                }
                                ++i;
                                delayPlaceBlock(Material.AIR, b.getLocation().add(0.0, 1 + i, 0.0), 90L);
                            }
                        }.runTaskTimer(instance, 100L, 20L);
    Which makes that after 5 seconds the method delayPlaceBlock executes 40 times.
    The method makes that the block above the location where the method is called get replaced for air. I read something about getHighestBlockYAt. I'll make a new thread later. Thanks!

    EDIT: Finally worked, it keeps repeating until there is no block above.
    Changed to solve. Thanks :D
     
    #13 AlonsoAliaga, Mar 7, 2018
    Last edited: Mar 7, 2018
Thread Status:
Not open for further replies.