How do you use ticks in bukkit?

3.2k Views Asked by At

I understand ticks, 20 ticks to a second etc. but i don't get the syntax. Can someone explain to me the steps of making something with ticks? I have a fireball move here as an example of something i need ticks for; after each time it does the effect, i need it to wait like, 2 ticks. I've looked at other examples but i really don't understand the syntax

@EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
    Player player = event.getPlayer();
    if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
        List<Block> targets = player.getLineOfSight((Set)null, 30);
        for (Block targetblock : targets){
            Location target = targetblock.getLocation();
            player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
        }
    }
}

I need to know how to add a delay to a loop, timing is really important in this plugin i'm trying to make and i just need to know the syntax. Anyone help?

2

There are 2 best solutions below

6
On

You will start using Scheduler Programming. Look carefully at this part of the tutorial.

You need a repeating task for this purpose:

  1. First, create a class that extends BukkitRunnable.
  2. Then override the Runnable.run() method: it will be called once per iteration.
  3. Now start the task with BukkitRunnable.runTaskTimer(Plugin, long, long).
  4. You can stop it at any time using BukkitRunnable.cancel().

You could implement the feature like this:

List<Block> blocks; // The target blocks
BukkitRunnable task = new MagmaEffect(blocks);
Plugin main; // The unique instance of the main class
task.runTaskTimer(main, 0L, 2L);

public class MagmaEffect extends BukkitRunnable {
    private List<Block> blocks;
    public MagmaEffect(List<Block> blocks) {
        this.blocks = blocks;
    }
    private int index;
    @Override
    public void run() {
        Block block = blocks.get(index);
        block.getWorld().playEffect(block.getLocation(), Effect.MOBSPAWNER_FLAMES, 5);
        index++;
        if (index == blocks.size()) {
            cancel();
        }
    }
}
2
On

To make a timer, you can use

Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
  public void run(){
    //code
  }
},ticksToWait);//run code in run() after ticksToWait ticks

So, if you wanted to wait 2 ticks before running the function shootFireball(), for example, you could use

Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
  public void run(){
    shootFireball();
  }
},2L);//run code in run() after 2 ticks

plugin will be the instance of your Main class (the one that extends JavaPlugin). So, for example, your onEnable and onDisable functions in your Main class could look like this:

public static Main that; //in your case "plugin" would be "Main.that"

@Override
public void onEnable(){
    that = this; //Main.that is now equal to this class
}

@Override
public void onDisable(){
    that = null; //Set to null to prevent memory leaks
}

So, your code could look something like this:

@EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
    Player player = event.getPlayer();
    if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
        List<Block> targets = player.getLineOfSight((Set)null, 30);
        for (int i = 0; i < targets.size(); i++){
            //call the spawnFlames with "i * 2" ticks, because
            //every time "i" is incremented, there is a new target block
            //which means we should wait 2 more ticks than the previous
            //iteration before running the task
            spawnFlames(player, targets.get(i), i * 2);
        }
    }
}

public void spawnFlames(final Player player, final Block target, final long ticks){
    Bukkit.getServer().getScheduler().runTaskLater(Main.that, new Runnable(){
        public void run(){
            Location target = targetblock.getLocation();
            player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
        }
    },ticks);
    //run code in run() after "ticks" ticks
    //"ticks" will be equal to "i * 2" from
    //the onPlayerInteractBlockFireBall() method
}