1

I've been trying to make gun plugin for Bukkit, and I'm trying to build a burst fire feature. I have a for loop that contains a delayed task, and inside that delayed task is the code to create a bullet and all that. Theoretically, the code would add some bullets, wait one tick, and add some more bullets, wait one tick, etc until the for loop is done.

public void fire(final Player p, final Gun g) {
    for(int i=0; i<shotsPerBurst; i++) {
        Bukkit.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, new Runnable() {
            public void run() {
                for(int i=0; i<bulletsPerShot; i++) {
                    Bullet b = new Bullet(p, g);
                    GunsV1.bullets.add(b);
                }
            }
        }, 1L);
    }
}

Eclipse demands that Player p and Gun g both be final, I don't know why, and when I try to run fire(p, g), nothing happens. How can I set up my code so the for loop will run with a delay of 1 tick between cycles?

Javed
  • 11
  • 2
  • 6

3 Answers3

0

To resolve one question:

Eclipse demands that Player p and Gun g both be final, I don't know why

You are passing the Player p and the Gun g to an new Thread/new Runnable and Eclipse tells you that those 2 Object's shouldn't be modified or changed because the Thread/Runnable also uses these 2 Object's inside the run method (as you can see).

I would suggest you to write your issue directly in here: http://bukkit.org/forums/plugin-development.5/ because there are also developer which know more and in detail about the Bukkit Server for Minecraft.

I will try to find a solution that fit's your needs now - but maybe you already try to find a solution in the forum.

Found this link for you - it may help you a little bit: http://www.programcreek.com/java-api-examples/index.php?api=org.bukkit.scheduler.BukkitScheduler

DominikAngerer
  • 6,354
  • 5
  • 33
  • 60
0

There's no easy way to run the for loop with a delay without freezing Bukkit's main thread. The best thing to do in this case is to use plugin.getServer().getScheduler().runTaskLater():

plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
  public void run(){
    //shoot the gun
  }
},1L);//run after 1 tick

But, if you use this, the gun will only fire one shot. To fix this, you should keep running the scheduler:

public static void runTask(){
  plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
    public void run(){
      //shoot the gun
      runTask(); //run the task again
    }
  },1L);//run after 1 tick
}

But this way, the gun will keep firing every tick, and never stop. So, you should count the number of times it has ran, and stop running the task once the number is reached:

public static void runTask(final int timesLeft){
  plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
    public void run(){
      //shoot the gun
      if(timesLeft > 0){
        runTask(timesLeft - 1); //run the task again after removing from the times left
      }
    }
  },1L);//run after 1 tick
}

So, in the end, your loop method could look something like this:

public static void fire(final Player player, final Gun gun, final int timesLeft){
  plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
    public void run(){
      Bullet bullet = new Bullet(player, gun);
      GunsV1.bullets.add(bullet);

      if(timesLeft > 0){
        fire(player, gun, timesLeft - 1); //run the task again after removing from the times left
      }
    }
  },1L);//run after 1 tick
}

and you could call it by using:

fire(player, gun, shotsPerBurst);
Jojodmo
  • 23,357
  • 13
  • 65
  • 107
0

After experimenting with some longer delays and looking at the spigot reference, I realized that the ticks of delay are not ticks until the next task, but until the runnable runs. Knowing this, I was able to use the for loop to increase the ticks of delay proportionally:

public void fire(final Player p, final Gun g) {
    for(int i=0; i<shotsPerBurst; i++) {
        Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
            public void run() {
                for(int i=0; i<bulletsPerShot; i++) {
                    Bullet b = new Bullet(p, g);
                    GunsV1.bullets.add(b);
                }
            }
        }, i*3);
    }
}

Now it runs each task three ticks after the previous one, and fires in a burst

Javed
  • 11
  • 2
  • 6
  • It solved the problem, but I don't know where to go from here as I am new to this site – Javed Apr 09 '15 at 00:49
  • you should upvote answers that helped you. Also, if an answer fixes your problem, you should accept it (that goes for all questions). But anyways, once you accept the answer that solves your problem, you're pretty much done. – Jojodmo Apr 09 '15 at 00:55