首先,这是与Minecraft / Bukkit相关的,但我相信我的问题不是Bukkit特有的,只是忽略了我想的小事(我希望)。
我的代码的最底部是randomDelay
和randomPeriod
。 run()
函数基于这两个变量以给定间隔重复运行。在runnable启动后,我不知道如何动态更改这些内容。我想让runnable的每个句点的长度不同,但问题是一旦run()
函数开始,它似乎使用了指定的第一个值。
package code.malon;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
public final class RandomResponse extends JavaPlugin {
Random rand = new Random();
int min = 20;
int max = 200;
long randomDelay = rand.nextInt((max - min) + 1) + min;
long randomPeriod = rand.nextInt((max - min) + 1) + min;
public void onEnable() {
BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
scheduler.scheduleSyncRepeatingTask(this, new Runnable() {
@Override
public void run() {
randomDelay = rand.nextInt((max - min) + 1) + min;
randomPeriod = rand.nextInt((max - min) + 1) + min;
}
}, randomDelay, randomPeriod);
}
}
答案 0 :(得分:2)
让我们来回答!哦,是的!
您的代码不是动态的,因为当Bukkit RandomResponse
构建PluginClassLoader
时,初始化这些字谜。这会创建一个new Random()
,生成一次随机值并安排它延迟“randomDelay
”。这不是动态的。让我们用小黑客解决这个问题:
public final class RandomResponse extends JavaPlugin {
final Random rand = new Random();
final int min = 20;
final int max = 200;
// I made these final for arbitrary reasons.
private RandomResponse randomResponse;
@Override
public void onEnable() {
randomResponse = this; // To use in anonymous class.
// The delay should be random, so we compute it within onEnable() method.
// We do not leave it in the class because then it's initialized by constructing.
long randomDelay = rand.nextInt((max - min) + 1) + min;
getServer().getScheduler().runTaskLater(this, new Runnable() {
@Override
public void run() {
/*
* Stuff to do
*/
// Call itself again some time later.
long randomDelay = rand.nextInt((max - min) + 1) + min;
getServer().getScheduler().runTaskLater(randomResponse, this, randomDelay);
}
}, randomDelay);
}
}
请注意,scheduleSyncRepeatingTask
在开始运行后不能更改任务的周期长度。因此,您必须以递归方式调用。要允许取消并重新运行任务,请使用以下命令:
BukkitTask task;
void runTask() {
cancelTask();
task = getServer().getScheduler().runTaskLater(this, new Runnable() {
@Override
public void run() {
/*
* Stuff to do
*/
// Call itself again some time later.
long randomDelay = rand.nextInt((max - min) + 1) + min;
task = getServer().getScheduler().runTaskLater(randomResponse, this, randomDelay);
}
}, randomDelay);
}
void cancelTask() {
if (task != null) try {
task.cancel();
} catch(Throwable ex) {
// Ignore.
}
}
作为您可能未发生的附注,您可能希望使用BukkitRunnable
代替Runnable
中的java.lang
类。
答案 1 :(得分:1)
将句点设置为每个刻度。
Task task = new Task();
task.runTaskTimer(Plugin, 1L, 1L);
然后使用索引并在每次达到随机延迟时重置它。
public class Task extends BukkitRunnable() {
private Random random = new Random();
private int index;
public Task() {
setRandom();
}
@Override
public void run() {
if (index == delay) {
// Work goes here
setRandom();
} else {
index++;
}
}
private void setRandom() {
index = random.nextInt(201) + 20;
}
}
答案 2 :(得分:0)
虽然使用Bukkit API无法实现,但您可以在CraftBukkit和Reflection的帮助下动态更新任务的周期。
public class TaskUtil {
public static Field CRAFTTASK_PERIOD;
static {
try {
CRAFTTASK_PERIOD = CraftTask.class.getDeclaredField("period");
CRAFTTASK_PERIOD.setAccessible(true);
} catch (Exception e) {
e.printStackTrace()
}
}
public static void updateTaskPeriod(int id, long period) {
CraftScheduler scheduler = (CraftScheduler) Bukkit.getScheduler();
scheduler.getPendingTasks().forEach(task -> {
if (task.getTaskId() == id) {
try {
CRAFTTASK_PERIOD.setLong(task, period);
} catch (Exception e) {
e.printStackTrace()
}
}
});
}
}
您还可以更进一步,通过利用Reflection从调度程序中获取排队任务,完全消除CraftBukkit依赖。