java - IllegalStateException: TimeSkipEvent 只能同步触发
问题描述
尝试异步更改世界时间时收到此消息
java.lang.IllegalStateException: TimeSkipEvent may only be triggered synchronously.
at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:595) ~[patched_1.16.3.jar:git-Paper-253]
at org.bukkit.craftbukkit.v1_16_R2.CraftWorld.setFullTime(CraftWorld.java:948) ~[patched_1.16.3.jar:git-Paper-253]
at org.bukkit.craftbukkit.v1_16_R2.CraftWorld.setTime(CraftWorld.java:936) ~[patched_1.16.3.jar:git-Paper-253]
at ru.lmpx.lmpxserverkit.handlers.NightSkipHandler.lambda$onPlayerSleep$0(NightSkipHandler.java:29) ~[?:?]
at org.bukkit.craftbukkit.v1_16_R2.scheduler.CraftTask.run(CraftTask.java:99) ~[patched_1.16.3.jar:git-Paper-253]
at org.bukkit.craftbukkit.v1_16_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:54) ~[patched_1.16.3.jar:git-Paper-253]
at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22) ~[patched_1.16.3.jar:git-Paper-253]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_271]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_271]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_271]
@EventHandler
public void onPlayerSleep(PlayerBedEnterEvent e) {
if (!(plugin.getConfig().getBoolean("skipNight.enable"))) return;
if (e.getBedEnterResult().equals(PlayerBedEnterEvent.BedEnterResult.OK)) {
if (plugin.getConfig().getBoolean("skipNight.instantSkip")) {
Bukkit.getWorld("world").setTime(0);
Bukkit.getWorld("world").setStorm(false);
} else {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
while (Bukkit.getWorld("world").getTime() < 24000) {
Bukkit.getWorld("world").setTime(Bukkit.getWorld("world").getTime() + 10);
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});
}
}
}
需要更改什么以便异步线程更改时间而不会出现 IllegalStateException 错误?
解决方案
异常是显式的,您不能异步调用同步方法。这是为了确保维护线程安全。要修复您的代码,您需要更改runTaskAsynchronously()
为runTask()
,但是,使用您当前的代码,这会冻结主线程。
更好的解决方案是使用该runTaskTimer()
方法。您可以创建一个扩展BukkitRunnable的新类。以下代码未经测试,但应该接近您的需要:
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.scheduler.BukkitRunnable;
public class BedTask extends BukkitRunnable {
@Override
public void run() {
World world = Bukkit.getWorld("world");
if(world.getTime() >= 24000){
this.cancel();
return;
}
world.setTime(world.getTime() + 10);
}
}
然后你可以像这样执行它:
int sleepWaitPeriod = 10;
new BedTask().runTaskTimer(plugin, 0L, sleepWaitPeriod * 20);
推荐阅读
- java - 如何获取匿名对象参数?
- asp.net - Like 不适用于特定类型的存储过程
- mysql - .net core 2.1 MVC for MySQL 数据库中的瞬态故障处理
- mysql - 在heroku上部署节点应用程序时如何连接mysql
- php - 线系列图在调整大小时出现错误 - highcharts
- machine-learning - 总误差平均值是回归模型的充分性能指标吗?
- python - 与 Pivot_Table 合并后结果列中的错误
- javascript - 我可以搜索一组函数并运行搜索到的函数吗?
- python-3.x - 如何更改顶部栏颜色 python
- angular - 如何在 Angular 7 中停止间隔?