我正在使用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);
}
答案 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,那就是你打算在将来停止任务。