【问题标题】:Bukkit Delayed Task Inside a For LoopFor 循环内的 Bukkit 延迟任务
【发布时间】:2015-04-05 23:55:41
【问题描述】:

我一直在尝试为 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 个滴答运行?

【问题讨论】:

    标签: java bukkit


    【解决方案1】:

    解决一个问题:

    Eclipse 要求玩家 p 和 Gun g 都是 final,我不知道为什么

    您将Player pGun g 传递给new Thread/new Runnable,Eclipse 告诉您不应修改或更改这两个Object,因为Thread/@ 987654329@ 在 run 方法中也使用了这 2 个 Object(如您所见)。

    我建议您直接在此处写您的问题:http://bukkit.org/forums/plugin-development.5/,因为也有开发人员更详细地了解 Bukkit Server for Minecraft。

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

    为您找到此链接 - 它可能对您有所帮助:http://www.programcreek.com/java-api-examples/index.php?api=org.bukkit.scheduler.BukkitScheduler

    【讨论】:

      【解决方案2】:

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

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

      但是,如果你使用这个,枪只会发射一发子弹。要解决此问题,您应该继续运行调度程序:

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

      【讨论】:

        【解决方案3】:

        在尝试了一些更长的延迟并查看了 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);
            }
        }
        

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

        【讨论】:

        • 它解决了问题,但我不知道从这里去哪里,因为我是这个网站的新手
        • 您应该为对您有帮助的答案投票。此外,如果答案解决了您的问题,您应该接受它(适用于所有问题)。但无论如何,一旦你接受了解决问题的答案,你就完成了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-01
        相关资源
        最近更新 更多