每2分钟调用一次功能

时间:2017-06-13 19:27:21

标签: java minecraft bukkit

我正在使用Minecraft服务器的插件,该服务器会自动打破甜瓜农场的甜瓜。它遍历所有玩家的所有街区。当前的块,并打破瓜块。起初,我尝试在while方法中使用onEnable循环连续调用此函数,但这会导致服务器时间/延迟。没有while循环(仅从onEnable调用函数一次),插件工作正常。每次我重新加载服务器时,该功能都会运行,所有甜瓜都会被破坏;所以我决定制作一个每两分钟调用一次功能的计时器。出于某种原因,服务器仍然超时,即使是计时器,我也不明白

这是我的代码:

package me.spigot.itiurray.main;

import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

public class Main extends JavaPlugin {
    private long goTime = 0;

    @Override
    public void onEnable() {
        getLogger().info("MelonDrop has been enabled.");
        startBreakWithInterval();
    }

    private void breakMelons() {
        for (Player player : Bukkit.getOnlinePlayers()) {
            Chunk chunk = player.getLocation().getChunk();

            int x = chunk.getX() << 4;
            int z = chunk.getZ() << 4;

            for (int xx = x; xx < x + 16; xx++) {
                for (int zz = z; zz < z + 16; zz++) {
                    for (int yy = 0; yy < 256; yy++) {

                        Block block = chunk.getBlock(xx, yy, zz);

                        if (block.getType().equals(Material.MELON_BLOCK))
                            block.breakNaturally();

                        goTime = System.currentTimeMillis() + 120000;
                    }
                }
            }
        }
    }

    private void startBreakWithInterval() {
        boolean running = true;

        while (running == true) {
            if (System.currentTimeMillis() >= getGoTime())
                breakMelons();
        }
    }

    private long getGoTime() {
        return goTime;
    }
}

编辑:这是目前的样子......

    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

    @Override
    public void onEnable() {
        getLogger().info("MelonDrop has been enabled.");    

        scheduledExecutorService.scheduleWithFixedDelay(() -> breakMelons(), 
2, 2, TimeUnit.MINUTES);
    }

5 个答案:

答案 0 :(得分:3)

您的代码卡在while(running == true)

我建议您使用ScheduledExecutorService

答案 1 :(得分:1)

根据您的时间逻辑,您应该执行以下操作

if(System.currentTimeMillis() - getGoTime() >= 120000)
{
    breakMelons();
}

然后在你的休息瓜功能中,只需在你的for循环之外的方法的最后调用它并执行以下操作

goTime = System.currentTimeMillis();

goTime变量应该只是你上次完成破坏所有甜瓜的时间。然后,当您根据当前系统时间检查该时间时,检查当前时间与上次执行瓜功能之间的时间差是否大于120000ms。

答案 2 :(得分:1)

更清晰的解决方案如下:

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
    @Override
    public void run() {
        breakMelons()
    }
}, 2, 2, TimeUnit.MINUTES);

这将每2分钟调用一次方法。此外,如果您支持java 8,那么您可以使用以下语法:

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

scheduledExecutorService.scheduleWithFixedDelay(() -> breakMelons(), 2, 2, TimeUnit.MINUTES);

答案 3 :(得分:1)

正确的解决方案是使用BukkitRunnable。您可以在bukkit's documentation

看到更多示例
JavaPlugin plugin;    //Your plugin instance    
Long timeInSeconds = 10;
Long timeInTicks = 20 * timeInSeconds;
new BukkitRunnable() {

@Override
public void run() {
    //The code inside will be executed in {timeInTicks} ticks.
   //After that, it'll be re-executed every {timeInTicks} ticks;
  //Task can also cancel itself from running, if you want to.

   if (boolean) {
       this.cancel();
   }

}
}.runTaskTimer(plugin, timeInTicks, timeInTicks);   //Your plugin instance, 
                                                   //the time to wait until first execution,
                                                  //the time inbetween executions.

答案 4 :(得分:-1)

大多数其他答案都使用BukkitRunnable和其他本机Java库。执行此操作的最佳方法是使用Runnable而不是BukkitRunnable使用计划任务。

Bukkit.getScheduler().scheduleSyncRepeatingTask(myPlugin, new Runnable() {

    @Override
    public void run() {
        breakMelons();
    }
}, 0, 2400);

以下代码使用推荐的重复运行简单任务的方式。

您不希望以另一个答案中推荐的方式使用BukkitRunnable的原因是因为它创建了一个被调用然后保持孤立的变量。此代码使用内联匿名内部类,以保持一切整洁,同时也给你相同的效果。

你想要使用BukkitRunnable而不仅仅是普通的Runnable,那就是你打算在将来停止任务。