Good Way to Have Timers

Discussion in 'Plugin Development' started by Shad, Jul 21, 2013.

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

    Shad

    Hey I've been looking for a good way to have timers but I can't think or find anything that meet certain criteria. I'm looking for a way to have timer that extends over a period of time (Hours) and persists through shutdowns, reloads ect. Using delay tasks doesn't really cut it because they don't persist through reloads, shutdowns, and so on.

    Any help would be greatly appreciated!
     
  2. Offline

    Bart

    You will just have to re-register them when you enable the plugin. No other way to do it.
     
  3. Offline

    Shad

    There's really no other way? If I re-register them they don't start off where it ended right?
     
  4. Offline

    Bart

    No but you could store some kind of value in a config file to continue where it left off, I guess.
     
  5. Offline

    soulofw0lf

    have the things that occur based on system time, but have a runnable check that that you start on enable
     
  6. Offline

    CubieX

    Use System.currentTimeMillies() to get the current timestamp.
    Then add the delay in milliseconds until the timer should execute his code and save that value to config.
    Use a repeating task to check if the predefined timestamp is < the current time every second or so,
    and if so, execute your code and re-schedule your timestamp for the next execution.

    This way, your timer will work even after restart, without you having to do anything.
     
    Shad likes this.
  7. Offline

    Shad


    Wow that's great, thanks a lot!

    CubieX
    I'm having trouble thinking of a way to grab information from the config to continue checking to see if the time has occurred yet.

    I'll tell you what I'm trying to accomplish with less vagueness: After a player mines an ore, it will spawn whatever time I set after it's been mined, it reappears. Not only am I having trouble retaining block information (ID, location, world), I'm having more trouble having it know to check for which blocks currently need to be spawned.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  8. Offline

    CubieX

    You would have to save the original block, its data, its location and a timestamp for its reappearing time then.
    This will be quite extensive data after a while.
    Thousands of blocks will mean thousands of entries in your file. Depending on how long you need to delay the reappearing of those ores.
    I can't say how much entries you can search through in one server tick, without impacting server performance (lag),
    but you can just try it.

    Using a database (SQLite ir MySQL) would not be bad here, but you can stick with a .yml file for now.

    Just think of a format to save those data.
    If I had to do this, I would structure my yml file like this, for example:
    Code:
    ores:
      world1:
        blockID: 13
          230_23_-459:
            restoreTimestamp: 1374584569423
          231_23_-459:
            restoreTimestamp: 1374584786354
        blockID: 56
          1308_10_-48:
            restoreTimestamp: 1374584566535
          256_11_-498:
            restoreTimestamp: 1374584786543
      world2:
        blockID: 14
          -1200_20_760:
            restoreTimestamp: 1374586453234
    But this is only an example how you could do it.
    And then delete the entry of a block that has been restored.
    So the file will not grow infinitely.

    Getting the TypeId, location and world of a block that has been mined can easily be done in the BlockBreakEvent.
    In my example, I concaternated x, y and z coordinate of the block with a _ as divider.
    You can save x, y and z as separate keys, if you want.
    Usually, I use this concaternated coordinates as unique identifier for a block in the world.
    That's why I do it that way.
    Later I split those coordinates when I need them as integers.
    But how you do this is entirely up to you.
     
  9. Offline

    Shad

    CubieX
    I had envisioned doing what you explained but what I'm having difficulties doing is sorting through those entries with the repeating task. An example would be getting the path up to restoreTimestamp to get the time to restore because I don't know what to put in the code for the block location (since it's part of the path to restoreTimestamp). Sorry if that's confusing to understand, I'm having a bit of trouble trying to explain it. I'm also having troubles telling the code to sort through the entries to check if it needs to be spawned.

    Also, thanks for all your help this far.
     
  10. Offline

    CubieX

    The Bukkit configuration system tutorial and also the plugin tutorial explains how to set and get data from a yml config.
    The basic method is this, to set data ( e.g. a block to restore later):
    Code:
    getConfig().set("ores." + world + "." + block.getTypeId() + "." + block.getX() + "_" + block.getY() + "_" + block.getZ() + ".restoreTimestamp", myRestoreTimestamp);
    Getting the timestamp from config would be the same, but with getConfig().getLong(...path.to.restoreTimestamp...)

    I can't give you the exact code for all of this, as you will have to check, if there is an entry for the blockID already present or not, and if not, create it before creating the entry for the timestamp.
    But you really have to understand this yourself. Play a bit with your yaml config to get the hang of it .
    Setting and getting keys and sub keys ect.
    It's not difficult at all. But you need to figure it out yourself, before doing such stuff.
     
  11. Offline

    ShadowDog007

    Shad

    You should load all of the blocks which need to be reset from the file on startup and store them in a queue (Make sure they are ordered) or an ordered set (TreeSet ?).

    You will need to make the class which stores block data and the timestable implement Comparable<YourClass> so you can put it in a TreeSet. Then all you have to to is fetch the first one in the set and check if that time has passed.

    The compare method should look something like this.
    Code:
    public int compare(YourClass o)
    {
        if (this.resetTime < o.resetTime)
            return -1;
     
        if (this.resetTime > o.resetTime)
            return 1;
     
        return this.hashCode() > o.hashCode() ? 1 : this.hashCode() != o.hashCode() ? -1 : 0;
    }
    Note, the bit at the bottom is just to allow for blocks which have the same reset time to exist in the set.

    Because it is ordered you can keep iterating through the set (Or queue) until you find one which is not supposed to be reset then stop until the task runs again.

    The last thing you want is to be loading data from the config every time you want to check if a block needs to be reset.
     
Thread Status:
Not open for further replies.

Share This Page