Bukkit 在 For 循环中延迟任务

Bukkit Delayed Task Inside a For Loop

我一直在尝试为 Bukkit 制作枪支插件,并且我正在尝试构建连发射击功能。我有一个包含延迟任务的 for 循环,在该延迟任务中是创建子弹的代码等等。从理论上讲,代码会添加一些项目符号,等待一次,然后添加更多项目符号,等待一次,等等,直到 for 循环完成。

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 要求 Player p 和 Gun g 都是 final,我不知道为什么,当我尝试 运行 fire(p, g) 时,没有任何反应。我如何设置我的代码,以便 for 循环 运行 在循环之间延迟 1 个滴答?

解决一个问题:

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

您正在将 Player pGun g 传递给 new Thread/new Runnable,Eclipse 告诉您这 2 个 Object 应该不会被修改或更改,因为 Thread/Runnable 也在 运行 方法中使用了这两个对象(如您所见)。

我建议您直接在这里写下您的问题:http://bukkit.org/forums/plugin-development.5/ 因为也有开发者对 Bukkit Server for Minecraft 了解得更多更详细。

我现在会尝试找到适合您需求的解决方案 - 但也许您已经尝试在论坛中找到解决方案。

为您找到了这个 link - 它可能会对您有所帮助:http://www.programcreek.com/java-api-examples/index.php?api=org.bukkit.scheduler.BukkitScheduler

在不冻结 Bukkit 的主线程的情况下,没有 简单 方法可以延迟 运行 for 循环。在这种情况下最好的办法是使用 plugin.getServer().getScheduler().runTaskLater():

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

但是,如果你使用这个,枪只会开一枪。要解决此问题,您应该 运行ning 调度程序:

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
}

但这样一来,枪就会一直开火,永远不会停止。因此,您应该计算它的次数 运行,并在达到该次数后停止 运行 任务:

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
}

因此,最后,您的循环方法可能如下所示:

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
}

您可以使用以下方式调用它:

fire(player, gun, shotsPerBurst);

在尝试了一些更长的延迟并查看了 spigot 参考之后,我意识到延迟的滴答声不是直到下一个任务才滴答,而是直到可运行对象运行。知道了这一点,我就能够使用 for 循环按比例增加延迟的滴答声:

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);
    }
}

现在它在前一个任务之后运行每个任务三个滴答,并突发