[Util] Simple Timer solution

Discussion in 'Resources' started by GameplayJDK, May 21, 2014.

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

    GameplayJDK

    I recently had to create a countdown for timing some actions (in one of my plugins). So I wrote a class for timing, which uses a BukkitTask to count down and run an action if one is set for the count value. I thought it could be useful for some of you :) .
    The Timer class (open)

    Code:java
    1.  
    2. package de.GameplayJDK.Code.Util;
    3.  
    4. import java.util.HashMap;
    5.  
    6. import org.bukkit.plugin.Plugin;
    7. import org.bukkit.scheduler.BukkitRunnable;
    8. import org.bukkit.scheduler.BukkitTask;
    9.  
    10. public class Timer {
    11.  
    12. public static interface TimerActionHandler {
    13. public void onAction(Timer parent);
    14. }
    15.  
    16. public static interface TimerHandler {
    17. public void onStart(Timer parent);
    18. public void onFinish(Timer parent);
    19. public void onCount(Timer parent);
    20. }
    21.  
    22. public static enum TimerState {
    23. PREINIT,
    24. RUNNING,
    25. PAUSED,
    26. FINISHED
    27. }
    28.  
    29. private Plugin plugin;
    30. private TimerHandler handler;
    31. private Long interval;
    32. private Integer length;
    33. private HashMap<Integer, TimerActionHandler> actions;
    34.  
    35. private Integer count;
    36. private BukkitTask task;
    37.  
    38. private TimerState state;
    39.  
    40. public Timer(Plugin plugin) { this.state = TimerState.PREINIT;
    41. this.actions = new HashMap<Integer, TimerActionHandler>();
    42. this.plugin = plugin;
    43. }
    44.  
    45. public Timer setTimerHandler(TimerHandler handler) { this.handler = handler;
    46. return this; }
    47.  
    48. public Timer setInterval(Long interval) { this.interval = interval;
    49. return this; }
    50.  
    51. public Timer setLength(Integer length) { this.length = length; this.count = length;
    52. return this; }
    53.  
    54. public Timer addTimerAction(Integer at, TimerActionHandler action) { this.actions.put(at, action);
    55. return this; }
    56.  
    57. public Timer removeTimerAction(Integer at) { if (this.actions.containsKey(at)) { this.actions.remove(at); }
    58. return this; }
    59.  
    60. public Timer start() {
    61. this.state = TimerState.RUNNING;
    62. handler.onStart(self());
    63. this.task = new BukkitRunnable() {
    64. @Override
    65. public void run() {
    66. if (state == TimerState.PAUSED) { return; } else if (state == TimerState.PREINIT) { task.cancel(); return; } else if (state == TimerState.FINISHED) { task.cancel(); return; }
    67. if (count <1) {
    68. state = TimerState.FINISHED;
    69. handler.onFinish(self());
    70. task.cancel();
    71. }
    72. handler.onCount(self());
    73. if (actions.containsKey(count)) { actions.get(count).onAction(self()); }
    74. count--;
    75. }
    76. }.runTaskTimer(this.plugin, this.interval, this.interval);
    77. return this; }
    78.  
    79. public Timer pause() { this.state = TimerState.PAUSED;
    80. return this; }
    81.  
    82. public Timer stop() { if (this.state != TimerState.FINISHED || this.task != null) { this.state = TimerState.FINISHED; this.task.cancel(); }
    83. return this; }
    84.  
    85. private Timer self() {
    86. return this; }
    87.  
    88. public Plugin getPlugin() {
    89. return this.plugin; }
    90.  
    91. public final TimerHandler getTimerHandler() {
    92. return this.handler; }
    93.  
    94. public final Long getInterval() {
    95. return this.interval; }
    96.  
    97. public final Integer getLength() {
    98. return this.length; }
    99.  
    100. public final HashMap<Integer, TimerActionHandler> getActions() {
    101. return this.actions; }
    102.  
    103. public final Integer getCount() {
    104. return this.count; }
    105.  
    106. public final BukkitTask getTask() {
    107. return this.task; }
    108.  
    109. public final TimerState getState() {
    110. return this.state; }
    111.  
    112. }
    113.  

    View the code as gist (open)


    And how to use it (open)

    Code:java
    1.  
    2. new de.GameplayJDK.Code.Util.Timer(owner)
    3. .setTimerHandler(new de.GameplayJDK.Code.Util.Timer.TimerHandler() { // Start, Stop and Tick actions
    4. @Override
    5. public void onStart(de.GameplayJDK.Code.Util.Timer parent) {
    6. // Do something when it starts..
    7. }
    8. @Override
    9. public void onFinish(de.GameplayJDK.Code.Util.Timer parent) {
    10. // Or when it's finished..
    11. }
    12. @Override
    13. public void onCount(de.GameplayJDK.Code.Util.Timer parent) {
    14. // And do something when it is counting!
    15. }
    16. })
    17. .setInterval(20L) // count -1 down every 20 ticks (servers mainly run with 20 TPS)
    18. .setLength(60) // count from 60 to 0 --> one minute
    19. .addTimerAction(30, new de.GameplayJDK.Code.Util.Timer.TimerActionHandler() { // TimerAction at 30 seconds
    20. @Override
    21. public void onAction(de.GameplayJDK.Code.Util.Timer parent) {
    22. // Now 30s are over.. Time to do something!
    23. }
    24. })
    25. .addTimerAction(5, new de.GameplayJDK.Code.Util.Timer.TimerActionHandler() { // TimerAction at 5 seconds
    26. @Override
    27. public void onAction(de.GameplayJDK.Code.Util.Timer parent) {
    28. // Oh! Only 5 seconds left! Hurry up!!!
    29. }
    30. })
    31. .start();
    32.  

    View the code as gist (open)

     
  2. Offline

    ccrama


    Pretty cool, but what are the advantages to using this rather than BukkitRunnables built into Bukkit?
     
  3. Offline

    GameplayJDK

    ccrama
    The timer is using a BukkitRunnable too :) But the advantage is, that you can really "time" actions. If you're using a normally scheduled BukkitTask you'd have to create a new one every time an old one has finished. And if you have more that 10 things to schedule, you'll have 10 different BukkitRunnables.. In my opinion it's easier to have just one main task and just add actions where you want them to happen :D
     
    ccrama likes this.
  4. Offline

    T0pAz7

    This is actually quite very useful. I don't like the complexity with dealing with timers for a minor task so this would definitely come handy.
     
  5. Offline

    GameplayJDK

Thread Status:
Not open for further replies.

Share This Page