IllegalStateException:TimeSkipEvent 只能同步触发
IllegalStateException: TimeSkipEvent may only be triggered synchronously
我在尝试异步更改世界时间时收到此消息
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[=10=](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 错误?
异常是显式的,您不能异步调用同步方法。这是为了确保 thread safety is upheld. To fix your code, you would need to change out runTaskAsynchronously()
with runTask()
,但是,对于您当前的代码,这会冻结主线程。
更好的解决方案是使用runTaskTimer()
method. You can create a new class that extends 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.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[=10=](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 错误?
异常是显式的,您不能异步调用同步方法。这是为了确保 thread safety is upheld. To fix your code, you would need to change out runTaskAsynchronously()
with runTask()
,但是,对于您当前的代码,这会冻结主线程。
更好的解决方案是使用runTaskTimer()
method. You can create a new class that extends 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);