Solved Performing actions at specific times

Discussion in 'Plugin Development' started by Fogest, Sep 30, 2012.

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

    Fogest

    Is there an easy way to call functions at specific times? By times, I'm talking real life time. Such as everyday at 7pm, plugin perform action xyz.
     
  2. Offline

    Deleted user

    Yes but I don't believe it's do able from within the Bukkit API, you would need to get it from a third party source.
     
  3. Offline

    Fogest

    Are you refering to getting the time from a third party source?
     
  4. Offline

    Deleted user

    Yes?
     
  5. Offline

    Fogest

    And what would I use to get this because I've seen many servers that have things that happen at specific times.
     
  6. Offline

    Timr

    "...have things happen..."

    What things are you referring to? Messages being broadcast, explosions being set off at specific locations?
     
  7. Offline

    Jnorr44

    He means in real life time
     
  8. Offline

    Fogest

    Essentially would begin a server event. By event I mean as in the form of some kind of PvP battle. I don't really think this makes a difference though. For example: Everyday at 7pm a Capture the Flag Event starts. How do I program the time part to see if time=7pm yet?
     
  9. Offline

    Sagacious_Zed Bukkit Docs

    This is one way to go about it.

    Read the current time.
    For each task figure out the duration remaining for the task.
    Schedule each task the number of ticks equal to the remaining duration.

    It gets more complex if you try to account for drift in the clock.
     
  10. Offline

    Fogest

    One task should not even be within a close time of another so accounting for ticks, and duration should not really matter. I just essentially need to know how to get the current time and check if time = 7pm (7 pm is an example)
     
  11. Offline

    Courier

    Javadocs are your friend. http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

    For example, this will get you the hour of the day, 0-23 inclusive:
    Code:java
    1. Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
     
  12. Offline

    Fogest

  13. Offline

    Sagacious_Zed Bukkit Docs

    No, if you want to get the current time, and the target time, it is much better to use the unix time to determine how many ticks you need.

    On a side note, the date utils from apache commons will be very helpful if you don't want to do the math yourself.
     
  14. Offline

    Fogest

    The times on this is not down to accuracy. I simply would like to check every 5 minutes (scheduled task), if the current hour is equal to the defined hour.
     
  15. Offline

    Courier

    You can do all of that with the Calendar class, and it doesn't require an external library. Let's say you want to schedule something for the next 7:00 pm:
    Code:java
    1. Calendar cal = Calendar.getInstance();
    2. long now = cal.getTimeInMillis();
    3. if(cal.get(Calendar.HOUR_OF_DAY) >= 19)
    4. cal.add(Calendar.DATE, 1); //do it tomorrow if now is after 7:00 pm
    5. cal.set(Calendar.HOUR_OF_DAY, 19);
    6. cal.set(Calendar.MINUTE, 0);
    7. cal.set(Calendar.SECOND, 0);
    8. cal.set(Calendar.MILLISECOND, 0);
    9. long offset = cal.getTimeInMillis() - now;
    10. long ticks = offset / 50; //there are 50 milliseconds in a tick
    11. Bukkit.scheduleSyncDelayedTask(plugin, task, ticks);

    Typed in forums; may be slightly incorrect.
     
  16. Offline

    Fogest

    But this does not repeat does it? And what is task suppose to be defined as ? I'm new to both Calendar and tasks, sorry :)
     
  17. Offline

    Courier

    In my last post, I said, "Bukkit.scheduleSync..." when I meant to say, "Bukkit.getScheduler().schedulerSync..."
    If you want to repeat it, you need to use scheduler.scheduleSyncRepeatingTask(). The task is a Runnable. The Runnable is usually defined as an anonymous inner class.
    Code:java
    1. Bukkit.scheduleSyncRepeatingTask(plugin, new Runnable()
    2. {
    3. public void run()
    4. {
    5. //CODE THAT RUNS
    6. //AT 7:00 PM EVERY DAY
    7. //GOES HERE
    8. }
    9. }, ticks, 24L * 60L * 60L * 1000L);
     
  18. Offline

    Fogest

    I've implemented your code, and it has no syntax errors, which is good. I'm just wondering if you can explain how the code works, as it does not help me too much, just copying this in. Also I would like to add a check for another time, so I need to understand how this works to do so. Thanks!
     
  19. Offline

    Courier

    I hope this further commented version will help you out.
    Code:java
    1. /**
    2.  * Schedules a task to run at a certain hour every day.
    3.  * @param plugin The plugin associated with this task
    4.  * @param task The task to run
    5.  * @param hour [0-23] The hour of the day to run the task
    6.  * @return Task id number (-1 if scheduling failed)
    7.  */
    8. public static int scheduleRepeatAtTime(Plugin plugin, Runnable task, int hour)
    9. {
    10. //Calendar is a class that represents a certain time and date.
    11. Calendar cal = Calendar.getInstance(); //obtains a calendar instance that represents the current time and date
    12.  
    13. //time is often represented in milliseconds since the epoch,
    14. //as a long, which represents how many milliseconds a time is after
    15. //January 1st, 1970, 00:00.
    16.  
    17. //this gets the current time
    18. long now = cal.getTimeInMillis();
    19. //you could also say "long now = System.currentTimeMillis()"
    20.  
    21. //since we have saved the current time, we need to figure out
    22. //how many milliseconds are between that and the next
    23. //time it is 7:00pm, or whatever was passed into hour
    24. //we do this by setting this calendar instance to the next 7:00pm (or whatever)
    25. //then we can compare the times
    26.  
    27. //if it is already after 7:00pm,
    28. //we will schedule it for tomorrow,
    29. //since we can't schedule it for the past.
    30. //we are not time travelers.
    31. if(cal.get(Calendar.HOUR_OF_DAY) >= hour)
    32. cal.add(Calendar.DATE, 1); //do it tomorrow if now is after "hours"
    33.  
    34. //we need to set this calendar instance to 7:00pm, or whatever.
    35. cal.set(Calendar.HOUR_OF_DAY, hour);
    36. cal.set(Calendar.MINUTE, 0);
    37. cal.set(Calendar.SECOND, 0);
    38. cal.set(Calendar.MILLISECOND, 0);
    39.  
    40. //cal is now properly set to the next time it will be 7:00pm
    41.  
    42. long offset = cal.getTimeInMillis() - now;
    43. long ticks = offset / 50L; //there are 50 milliseconds in a tick
    44.  
    45. //we now know how many ticks are between now and the next time it is 7:00pm
    46. //we schedule an event to go off the next time it is 7:00pm,
    47. //and repeat every 24 hours.
    48. return Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, task, ticks, 1728000L);
    49. //24 hrs/day * 60 mins/hr * 60 secs/min * 20 ticks/sec = 1728000 ticks
    50. }
    Example usage:
    Code:text
    1. scheduleRepeatAtTime(this, new Runnable()
    2. {
    3. public void run()
    4. {
    5. Bukkit.broadcastMessage("It is now noon. Yay.");
    6. }
    7. }, 12);

    EDIT: In one of my earlier posts, I accidentally said "24 * 60 * 60 * 1000"... that gets how many milliseconds are in a day, instead of ticks.
     
    piepiepie likes this.
  20. Offline

    Fogest

    WOW this is a HUGE help. Most people just link to the API, which barely helps with the understanding of the usage, whereas what you have done helps A LOT. Not only do I understand the calendar and scheduler better, I also could implement it in the future without help!

    Thanks!

    Just wondering, due to the way this works, it does not make a difference whether I put the "Usage" code in the onEnable or in a separate class to be called, does it ?
     
  21. Offline

    Courier

    It will work from anywhere.
     
  22. Offline

    Fogest

    Splendid. I will be sure to credit you if I ever use this in a public plugin. (Right now there is not plan for this, it's just to be used for 1 server)
     
Thread Status:
Not open for further replies.

Share This Page