Timer not working.

Discussion in 'Plugin Development' started by Dreeass, May 30, 2012.

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

    Dreeass

    I'm making a count down system every quarter time of the timer specified, so for example when the time specified is 60. Then it will say after 15 seconds: There are still 45 seconds remaining and when it reaches zero it stops and does some other stuff.

    But the time that I specified isn't working correctly, I specified a time of 600 and set the timer to getConfig().getInt(path)/4. But when I tell it to start and from on then it just goes rapidly from the first statement that it has to do to the last one.

    Here is some code:

    The secondConvert method just returns a string so there shouldn't be a problem there.
    Code:java
    1.  
    2.  
    3.  
    4. public String timeLeft = "unknown";
    5.  
    6. public String timeConvert(int i) {
    7. int d = i / 86400;
    8. int drem = i % 86400;
    9. int h = drem / 3600;
    10. int hrem = drem % 3600;
    11. int m = hrem / 60;
    12. int s = hrem % 60;
    13.  
    14. String days = secondConvert("day", d);
    15. String hours = secondConvert("hour", h);
    16. String mins = secondConvert("minute", m);
    17. String secs;
    18. if(secondConvert("minute", m).equals("")) {
    19. secs = secondConvert("second", s);
    20. }
    21. else {
    22. secs = "and " + secondConvert("second", s);
    23. }
    24.  
    25. String t = days + hours + mins + secs;
    26. timeLeft = t;
    27. return t;
    28. }
    29. public Timer timer;
    30. public int count = 0;
    31. public void Timer() {
    32. timer = new Timer(getConfig().getInt("Config.RoundLength") / 4, new TimerListener(this));
    33. timer.start();
    34. }
    35. public String secondConvert(String n, int i) {
    36. if(!(i > 0)) {
    37. s = "";
    38. return s;
    39. }
    40. if(i == 1) {
    41. s = i + " " + n + " ";
    42. return s;
    43. }
    44. s = i + " " + n + "s ";
    45. return s;
    46. }
    47.  

    This is the TimerListener class:
    Code:java
    1. package me.Dreeass.Play;
    2.  
    3. import java.awt.event.ActionEvent;
    4. import java.awt.event.ActionListener;
    5.  
    6. import org.bukkit.entity.Player;
    7.  
    8. public class TimerListener implements ActionListener {
    9.  
    10. public static Main plugin;
    11.  
    12. public TimerListener(Main instance) {
    13. plugin = instance;
    14. }
    15.  
    16. @Override
    17. public void actionPerformed(ActionEvent arg0) {
    18. plugin.count++;
    19. int count = plugin.count;
    20. int time = plugin.getConfig().getInt("Config.RoundLength");
    21. switch(count) {
    22. case 1:
    23. plugin.timeConvert(count/4 * time);
    24. plugin.BukkitMsgConvert("Messages.Start/Stop.Broadcast.Remaining", null);
    25. break;
    26. case 2:
    27. plugin.timeConvert(count/4 * time);
    28. plugin.BukkitMsgConvert("Messages.Start/Stop.Broadcast.Remaining", null);
    29. break;
    30. case 3:
    31. plugin.timeConvert(count/4 * time);
    32. plugin.BukkitMsgConvert("Messages.Start/Stop.Broadcast.Remaining", null);
    33. break;
    34. case 4:
    35. plugin.BukkitMsgConvert("Messages.Start/Stop.Broadcast.Ended", null);
    36. plugin.started = false;
    37. plugin.loading = false;
    38. plugin.players();
    39. for(Player p : plugin.players()) {
    40. p.setHealth(20);
    41. p.setFoodLevel(20);
    42. plugin.Sneak(p, false);
    43. p.teleport(plugin.getLocation("WatchSpawn"));
    44. plugin.MessageConvert("Messages.Start/Stop.Ended", p);
    45. }
    46. plugin.team1Players.clear();
    47. plugin.team2Players.clear();
    48. plugin.ffaPlayers.clear();
    49. plugin.timer.stop();
    50. plugin.count = 0;
    51. break;
    52.  
    53. }
    54. }
    55.  
    56. }
    57.  


    Ok I see that I had to multiply the Timer's delay with 1000 because it was in ms..

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 26, 2016
  2. Don't use timers with bukkit! Use the scheduler, that's what it was made for. Otherwise, you have some severe concurrency problems.
    And you are using a swing timer, which is even worse (without a swing GUI). Your task will be executed by the event dispatcher thread, that's murder for a minecraft server.
     
    ferrybig likes this.
  3. Offline

    Dreeass

    It's working now, it was a little mistake that was wrong. But why is the swing timer a murder for a minecraft server?
     
  4. If you don't know what threading is and how it works, this is very difficult to explain.
    There is a huge difference between it works and it works safely.

    Basically, imagine a thread is something that calls methods. When there are multiple of them, stuff happens at the same time. The minecraft server (as well as the bukkit API) is not designed to be used by multiple threads (from the outside).

    Imagine the server is one big machine, moving its players and mobs around, loading and unloading chunks and so on.
    Now when you do something asynchronously (= from a different thread), you break out of that machine and you start randomly throwing in stuff. 90% of the cases what you throw in might hit its target and work as expected, but at some point it's going to hit a part of the machine where it causes damage.

    It's unpredictable, that's why any method call from a different thread (with some exceptions) can potentially cause world corruption and server crashes.

    Back to your timer: Swing is a graphical API. That means it is designed to work with applications that use graphical swing elements.
    Like I said, the timer task will be executed by the event dispatcher thread. That's what a swing application uses to process window events. On a minecraft server, because it doesn't use a GUI, that thread doesn't even exist. Thus, all kinds of swing classes need to be loaded and that thread needs to be launched and kept running just for the sake of your timer.
    While this is bad enough, the concurrency problem described above (you throwing in random stuff into a big machine) is the worst.


    I don't expect you to understand all this, it is really complicated. If you want to try to understand it a bit more, feel free to read this tutorial: http://download.oracle.com/javase/tutorial/essential/concurrency/

    But please, please: Never use threading unless you know how to use it properly! Its effects are not instantly visible, but they will eventually cause severe damage to the server.

    http://wiki.bukkit.org/Scheduler_Programming
    The scheduler should be used when working with delays/timers.
    Also here: make sure you never use any method that has "Async" in its name, then you will be back at threading!
     
    ferrybig likes this.
  5. Offline

    Dreeass

    Bone008
    Thanks for the information, currently I have made some methods which make it so if you put the length of a round to 600 and the amount of messages to display in that time period. For example if I put 600 and 4 in, then it would put out every 150 seconds: 2 minutes and 30 seconds remaining.

    Is there any other way of doing this then?
     
  6. create an task that run every 150 sec or 3000 ticks
     
  7. Offline

    Dreeass

    I already figured a method out a method so you can configure it, but thanks.
     
Thread Status:
Not open for further replies.

Share This Page