Schedulers

Discussion in 'Plugin Development' started by number1_Master, Jan 9, 2012.

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

    number1_Master

    ya thats the one thing i have an issue with, the for loop...
    with this, the for loop is like invisible, whether it is within, or around the statement :/
    (by the use of the for loop, i mean so that the lightning can keep striking over and over a few times)
     
  2. Offline

    desht

    I think what's needed is to take a step back and re-evaluate the problem. You don't want to use a for or while loop here. You're working with event-driven programming, so you can't just take over the server thread to run a for loop with a delay (but I suspect you know that by now :) )

    @V10lator 's example is a good way to do it (I'm not sure getting a uuid is necessary, when scheduleSyncRepeatingTask() returns a unique ID anyway, but it's a valid approach). You basically need to set up a sync repeating task (using the Scheduler scheduleSyncRepeatingTask() method) which calls a lightning strike in the target object's run() method, and then cancels itself after a given number of calls to the method.

    The important thing to realise here is that this is event-driven, not straightforward procedural, programming. The code you write that responds to events (and I'm including scheduler callbacks in this) needs to work as quickly as possible to avoid creating server lag. Bearing in mind that one server tick is 50ms, all plugin event handlers need to complete in at most 50ms minus some server overhead - otherwise you'll get the dreaded "Can't keep up!" messages in your server log.
     
    nunber1_Master likes this.
  3. The problem is to give that ID to the task, so it can cancel itself. That's why I'm using a HashMap with a UUID as the key and the task ID as value. Possibly something like this would work, too:
    Code:java
    1. TestTask task = new TestTask(this);
    2. task.setPid(getServer().getScheduler().scheduleSyncRepeatingTask(this, task, 1L, 1L));

    Code:java
    1. public class TestTask implements Runnable
    2. {
    3. private final YourPlugin plugin;
    4. private int pid;
    5. public TestTask(YourPlugin plugin)
    6. {
    7. plugin = plugin;
    8. }
    9. public void run()
    10. {
    11. plugin.getServer().getScheduler().cancelTask(pid);
    12. }
    13. public void setPid(int pid)
    14. {
    15. this.pid = pid;
    16. }
    17. }
     
  4. Offline

    desht

    Personally, I'd do it like this (untested, apologies for any typos):
    Code:java
    1.  
    2. public class LightingStrike implements Runnable
    3. {
    4. private int taskId;
    5. private int repeats;
    6. private Location loc;
    7.  
    8. public LightningStrike(Location loc, long delay, int repeats)
    9. {
    10. this.loc = loc;
    11. this.repeats = repeats;
    12.  
    13. taskId = Bukkit.getServer().scheduleSyncRepeatingTask(plugin, this, 1L, delay));
    14. }
    15. public void cancel() {
    16. Bukkit.getServer().getScheduler().cancelTask(taskId);
    17. }
    18.  
    19. public void run() {
    20. if (repeats-- <= 0) {
    21. cancel();
    22. } else {
    23. loc.getWorld().strikeLightning(loc);
    24. }
    25. }
    26. }
    27.  

    Then you can say something like:
    Code:java
    1.  
    2. // schedule 10 strikes, 0.25 seconds apart
    3. LightningStrike ls = new LightningStrike(loc, 5L, 10);
    4.  

    You may or may not want to keep a copy of the return value. You might want the ability to cancel the strike partway through, for example (using ls.cancel()).

    There's a lot that could be added to this, e.g.:
    • Have lightning strikes randomly within a configurable radius around loc
    • Configurable start delay
    • Configurable autostart (i.e. don't start until a start() method is called)
    • Configurable whether it does real damage or just for show
    But that's a good basis to work from :)
     
    nunber1_Master likes this.
  5. Offline

    number1_Master

    at the moment, i think most of the code you guys have posted (which are amazing :D ) is probably unnecessary. i think i can figure it out if i know how to stop a repeating task. (you guys probably mentioned that within your code, or posts, but im in a rush so...)
     
  6. Offline

    number1_Master

    sorry for the late reply, but, i can't seem to get this to work within and onCommand statement
    (yes, i have been experimenting)
     
  7. Paste what you have so far, so we can help
     
  8. Offline

    number1_Master

    Code:java
    1.  
    2. [USER=4618]tips48[/USER] this is what i had before in an on command statement
     
  9. We need the updated code :)
     
    nunber1_Master likes this.
  10. Offline

    number1_Master

    before this was within a for loop, a if statement, and a while loop.
    also, i have been switching between a repeating task, and a delayed task.
    here is what i have (had):
    Code:java
    1.  
    2. plugin.getServer().getScheduler().scheduleSyncDelayedTask([B]this[/B].plugin, [B]new[/B] Runnable()
    3. {
    4. [B]public[/B] [B]void[/B] run()
    5. {
    6. world.strikeLightningEffect(loc);
    7. world.createExplosion(loc, 0);
    8. }
    9. }, 20L);
     
  11. nunber1_Master
    That code will wait one second, strike a lightning effect and create a explosion. Is that what you want?
     
  12. Offline

    number1_Master

    no
    yes i know what it does
    what im looking for is something that will strike lightning x many times, with a delay of 3L (not 20L, 20L was just because im fooling around with it)
     
  13. Multiple people already gave you the code above.
    Check the posts from desht and V10lator , and if you can't implement it yourself you might want to take a couple more java tutorials :)
     
  14. Offline

    number1_Master

    thats what ive been doing
    its just hard to do that within onCommand
    well, back to more studying! :/
     
  15. It shouldn't be that hard from onCommand...Your given the code more than once. Specifically:
    Code:java
    1.  
    2. TestTask task = new TestTask(this);
    3. task.setPid(getServer().getScheduler().scheduleSyncRepeatingTask(this, task, 1L, 1L));
    4.  
     
  16. Offline

    number1_Master

    i know
    im just trying to it differently :p

    i feel stupid, the answer is probably staring me right in the face, yet i dont understand it
    to me, the easiest way would be this, but doesnt work:
    Code:java
    1.  
    2. for(int counter=0;counter<=20;counter++)
    3. {
    4. plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, new Runnable()
    5. {
    6. public void run()
    7. {
    8. world.strikeLightningEffect(loc);
    9. world.createExplosion(loc, 0);
    10. }
    11. }, 20L);
    12. }
    13.  

    since that doesn't work, in my mind i just want to do this, about 20 times:
    Code:java
    1.  
    2. plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, new Runnable()
    3. {
    4. public void run()
    5. {
    6. world.strikeLightningEffect(loc);
    7. world.createExplosion(loc, 0);
    8. }
    9. }, 20L);
    10.  
    11. EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  17. This will strike 21 lightnings in the same tick... :confused:
    Also I'll bet you have a problem transferring "world" to the task...
     
  18. Offline

    number1_Master

    no
    i have tried just that once, and it works fine
    except i cant get it to repeat it
     
  19. Cause a delayed task != a repeating task. If you start a delayed task 21 times with the same delay it will execute 21 times at the same tick = 21 lightning strikes in one tick...
     
  20. Offline

    number1_Master

    as for as my testing has gone (on a server), and what i know, it has not struck lightning 21 times in about 1 tick
     
Thread Status:
Not open for further replies.

Share This Page