adddind a timer to an event

Discussion in 'Plugin Development' started by Kostronor, May 22, 2011.

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

    Kostronor

    Hello there,
    i have a problem with handeling a BlockBreakEvent
    After placing the block, i want the plugin to wait a certain time (up to 20 seconds) and then perform some actions with it.
    i tryed it with Thread.sleep(), but that just laggs the whole server and canceled the event after about 5 seconds.
    Has someone a better solution for this?
     
  2. Offline

    garbagemule

    When you call Thread.sleep(), what you're actually doing is making the main server thread sleep. To achieve what you want, you need to make a new thread that you can sleep. For this purpose, you can use BukkitScheduler. Call getScheduler() on the Server object to get the BukkitScheduler, and then call the scheduleSyncRepeatingTask-method listed in the link. You will have to provide the method with a class that implements the Runnable-interface and implements the run()-method. You can do this by either making an anonymous class, or making a new named class, that you create an object from.

    When you say "up to 20 seconds", do you mean it should periodically check, if something has happened, and then after 20 seconds do nothing, if that something hasn't happened? In that case, you should call sleep() with a value smaller than 20 seconds (20,000), because the sleep() method guarantees that the thread does not continue until that amount of time has passed. You could do this:
    Code:
    ...
    private int count = 0;
    ...
    public void run()
    {
        while (count < 20)
        {
            // Check if 'something' has happened
            count++;
            sleep(1000);
        }
    }
    This will cause the thread to sleep for approximately 1 second in every check. More generally, you can declare interval and termination field variables, and have the while-loop do the calculations needed. You could also use System.getTimeInMillis() to initialize a "start time" field, and then check if the current value is 20 seconds greater than the start time.

    I'm not entirely sure if this would ramp up a serious amount of active threads very quickly, though, so do a little testing before deciding to stick with it entirely ;)
     
    mxE333xm likes this.
  3. Offline

    Kostronor

    Thanks for this quick reply :)
    But i think, the problem is a bit different, here is an example code:
    Code:
        public void onBlockPlace(BlockPlaceEvent e){
            if (e.getBlock().getTypeId() == 6){
                int data = e.getBlock().getData();
                TreeType tt = getTree(data);
                Location location = e.getBlockPlaced().getLocation();
                World world = e.getPlayer().getWorld();
                /*
                 * Here should be the waiting-time
                 *  i don't know how much time it should be but perhaps,
                 *  i'll make a random time between 10-20 seconds.
                 *  It should actually work like: waiting(milliseconds time)
                 *  just wait the time when the method is used
                 *  */
                e.getBlock().setTypeId(0);
                world.generateTree(location, tt);
            }
        }
    Hope this makes the problem clear ;)
    After a sapling is placed, it should wait 10-20 seconds until growing a tree
     
  4. Offline

    garbagemule

    Ah! Then it is actually fairly simple :)

    Assuming you have a "plugin" field:
    Code:
    /* Generate a random number between 10 and 20 here,
     * and store it in an int called "delay" */
    plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin,
        new Runnable()
        {
            public void run()
            {
                e.getBlock().setTypeId(0);
                world.generateTree(location, tt);
            }
        }, delay*20);
    You might have some issues with variables needing to be declared final, but that shouldn't be too difficult. Alternatively, you can make a class that implements Runnable, like I mentioned in my first post, and then make an object from that class (feeding it the variables it needs) and feed it to the schedule method. The reason you need to multiply by 20 is that the delay must be in "server ticks", and 20 server ticks = 1 second.

    I haven't tested this out, but let me know if it works :)
     
  5. Offline

    Shamebot

    I think what you're looking for is scheduleSyncDelayedTask
    Code:
        public void onBlockPlace(BlockPlaceEvent e){
            if (e.getBlock().getTypeId() == 6){
                final Block block = e.getBlock();
                getServer().getScheduler().scheduleSyncDelayedTask(this,
                new Runnable()
                {
                    public void run()
                    {
                        TreeType tt = getTree(block.getData());
                        block.setTypeId(0);
                        world.generateTree(block.getLoaction, tt);
                    }
                },20000);
            }
        }
    Yeah same as garbagemule, didn't test this too.
     
  6. Offline

    garbagemule

    If you feed the schedule-method a delay of 20,000, it will take a bit more than 10-20 seconds for the tree to be generated :D
     
  7. Offline

    Shamebot

    Yes I thought a tick was 20 ms until I saw you post
     
    garbagemule likes this.
  8. Offline

    Kostronor

    Problem: getServer is no method in my plugin. and i don't have a field plugin. haven't needed it jet thought...
    Ok, i try it now with e.getPlayer().getServer and so on :D
    Thanks for your help!

    Edit:
    now its like this:
    Code:
     if (e.getBlock().getTypeId() == 6){
                    final Block block = e.getBlock();
                    final TreeType tt = getTree(block.getData());
                    final World world = e.getPlayer().getWorld();
                    e.getPlayer().getServer().getScheduler().scheduleSyncDelayedTask((Plugin) this,
                    new Runnable()
                    {
                        public void run()
                        {
                            block.setTypeId(0);
                            world.generateTree(block.getLocation(), tt);
                        }
                    },400);
                }
    but the tree is generated instantly...
     
  9. Offline

    Shamebot

    It should be inherited from JavaPlugin. Eclipse didn't give me an error when I tried it.
    Is your listener in your plugin class?
     
  10. Offline

    Kostronor

    no, my listener is it's own class.
    I includet my source, so you can look if somethings wrong
     

    Attached Files:

    • src.zip
      File size:
      2.1 KB
      Views:
      3
  11. Offline

    garbagemule

    Your "plugin" field is called "parent" :)
     
  12. Offline

    Kostronor

    well... silly me :D
    another thing i learned :D
    thanks, i think, it will work now, will test it the day thought :)
     
  13. Offline

    Shamebot

    That explains it, I'm usually including the listener in my plugin class, something like:
    Code:
    public void onEnable(){
        BlockListener blockListener = new BlockListener(){
            @Override
            public void onBlockPlace(...){
                 ...
            }
        };
        getServer().getPluginManager(...);
    }
    Just because it's less effort, nothing wrong with your way.
    Code:
    ((int)(Math.random() * 2)) == 0
    Is a strage way to say Math.random < 0.5
     
Thread Status:
Not open for further replies.

Share This Page