I get this message when trying to change the world time asynchronously
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();
}
}
});
}
}
}
What needs to be changed so that the asynchronous thread changes time without an IllegalStateException error?
The exception is explicit, you cannot call a synchronous method asynchronously. This is to ensure that thread safety is upheld. To fix your code, you would need to change out runTaskAsynchronously()
with runTask()
, however, with your current code, this would freeze the main thread.
A better solution is to use the runTaskTimer()
method. You can create a new class that extends BukkitRunnable. The below code is untested but it should be close to what you need:
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);
}
}
And you could then execute it like:
int sleepWaitPeriod = 10;
new BedTask().runTaskTimer(plugin, 0L, sleepWaitPeriod * 20);