From 7f412f5472eb79d241569e3c14e61b5575cdcab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 15 Jul 2020 13:18:09 +0200 Subject: [PATCH 1/5] Begin work on the task system --- .../plotsquared/bukkit/BukkitPlatform.java | 20 ++- .../bukkit/inject/BukkitModule.java | 6 + .../bukkit/listener/ChunkListener.java | 17 +- .../bukkit/listener/PlayerEvents.java | 5 +- .../bukkit/queue/ChunkCoordinator.java | 4 +- .../bukkit/util/BukkitRegionManager.java | 7 +- .../bukkit/util/BukkitTaskManager.java | 81 ---------- .../util/task/BukkitPlotSquaredTask.java | 46 ++++++ .../bukkit/util/task/BukkitTaskManager.java | 94 +++++++++++ .../bukkit/util/task/PaperTimeConverter.java | 47 ++++++ .../bukkit/util/task/SpigotTimeConverter.java | 47 ++++++ .../plotsquared/core/command/CmdConfirm.java | 11 +- .../plotsquared/core/command/Condense.java | 4 +- .../core/configuration/Settings.java | 6 +- .../core/generator/HybridUtils.java | 5 +- .../core/listener/PlotListener.java | 5 +- .../java/com/plotsquared/core/plot/Plot.java | 15 +- .../core/plot/comment/CommentManager.java | 3 +- .../core/plot/expiration/ExpireManager.java | 17 +- .../core/queue/GlobalBlockQueue.java | 3 +- .../plotsquared/core/util/ChunkManager.java | 3 +- .../core/util/SchematicHandler.java | 3 +- .../core/util/task/ObjectTaskRunnable.java | 4 +- .../core/util/task/PlotSquaredTask.java | 90 +++++++++++ .../core/util/task/TaskManager.java | 136 ++++++++++++---- .../plotsquared/core/util/task/TaskTime.java | 150 ++++++++++++++++++ 26 files changed, 666 insertions(+), 163 deletions(-) delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitPlotSquaredTask.java create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/task/PlotSquaredTask.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/task/TaskTime.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java index e40b6698e..256736ff7 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java @@ -44,11 +44,13 @@ import com.plotsquared.bukkit.placeholder.PlaceholderFormatter; import com.plotsquared.bukkit.placeholder.Placeholders; import com.plotsquared.bukkit.player.BukkitPlayerManager; import com.plotsquared.bukkit.util.BukkitChatManager; -import com.plotsquared.bukkit.util.BukkitTaskManager; +import com.plotsquared.bukkit.util.task.BukkitTaskManager; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitWorld; import com.plotsquared.bukkit.util.SetGenCB; import com.plotsquared.bukkit.util.UpdateUtility; +import com.plotsquared.bukkit.util.task.PaperTimeConverter; +import com.plotsquared.bukkit.util.task.SpigotTimeConverter; import com.plotsquared.bukkit.uuid.BungeePermsUUIDService; import com.plotsquared.bukkit.uuid.EssentialsUUIDService; import com.plotsquared.bukkit.uuid.LuckPermsUUIDService; @@ -105,6 +107,7 @@ import com.plotsquared.core.util.ReflectionUtils; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.uuid.CacheUUIDService; import com.plotsquared.core.uuid.UUIDPipeline; import com.plotsquared.core.uuid.offline.OfflineModeUUIDService; @@ -215,9 +218,16 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass; @Override public void onEnable() { this.pluginName = getDescription().getName(); + final TaskTime.TimeConverter timeConverter; + if (PaperLib.isPaper()) { + timeConverter = new PaperTimeConverter(); + } else { + timeConverter = new SpigotTimeConverter(); + } + // Stuff that needs to be created before the PlotSquared instance PlotPlayer.registerConverter(Player.class, BukkitUtil::getPlayer); - TaskManager.setImplementation(new BukkitTaskManager(this)); + TaskManager.setImplementation(new BukkitTaskManager(this, timeConverter)); final PlotSquared plotSquared = new PlotSquared(this, "Bukkit"); @@ -370,7 +380,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass; this.setGenerator(world); } } - }, 1); + }, TaskTime.ticks(1L)); } // Services are accessed in order @@ -500,7 +510,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass; this.startMetrics(); if (Settings.Enabled_Components.WORLDS) { - TaskManager.getImplementation().taskRepeat(this::unload, 20); + TaskManager.getImplementation().taskRepeat(this::unload, TaskTime.seconds(1L)); try { singleWorldListener = getInjector().getInstance(SingleWorldListener.class); } catch (Exception e) { @@ -960,7 +970,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass; } catch (Throwable e) { e.printStackTrace(); } - }), 20); + }), TaskTime.seconds(1L)); } @Override @Nullable diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java index c6fe99ba7..e3e18b04b 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java @@ -26,6 +26,8 @@ package com.plotsquared.bukkit.inject; import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.util.Providers; import com.plotsquared.bukkit.BukkitPlatform; @@ -39,6 +41,8 @@ import com.plotsquared.bukkit.util.BukkitPermHandler; import com.plotsquared.bukkit.util.BukkitRegionManager; import com.plotsquared.bukkit.util.BukkitSetupUtils; import com.plotsquared.bukkit.util.BukkitUtil; +import com.plotsquared.bukkit.util.task.PaperTimeConverter; +import com.plotsquared.bukkit.util.task.SpigotTimeConverter; import com.plotsquared.core.PlotPlatform; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.generator.HybridGen; @@ -60,8 +64,10 @@ import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.WorldUtil; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.extension.platform.Actor; +import io.papermc.lib.PaperLib; import lombok.RequiredArgsConstructor; import org.bukkit.Bukkit; import org.bukkit.command.ConsoleCommandSender; diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java index c22df7c54..7f7143758 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java @@ -26,7 +26,6 @@ package com.plotsquared.bukkit.listener; import com.google.inject.Inject; -import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.Plot; @@ -34,7 +33,9 @@ import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.util.ReflectionUtils.RefClass; import com.plotsquared.core.util.ReflectionUtils.RefField; import com.plotsquared.core.util.ReflectionUtils.RefMethod; +import com.plotsquared.core.util.task.PlotSquaredTask; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -53,10 +54,10 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkUnloadEvent; -import javax.annotation.Nonnull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; import java.lang.reflect.Method; import java.util.HashSet; @@ -132,7 +133,7 @@ public class ChunkListener implements Listener { } catch (Throwable e) { e.printStackTrace(); } - }, 1); + }, TaskTime.ticks(1L)); } public boolean unloadChunk(String world, Chunk chunk, boolean safe) { @@ -254,16 +255,16 @@ public class ChunkListener implements Listener { private void cleanChunk(final Chunk chunk) { TaskManager.index.incrementAndGet(); final Integer currentIndex = TaskManager.index.get(); - Integer task = TaskManager.runTaskRepeat(() -> { + PlotSquaredTask task = TaskManager.runTaskRepeat(() -> { if (!chunk.isLoaded()) { - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); + TaskManager.tasks.get(currentIndex).cancel(); TaskManager.tasks.remove(currentIndex); chunk.unload(true); return; } BlockState[] tiles = chunk.getTileEntities(); if (tiles.length == 0) { - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); + TaskManager.tasks.get(currentIndex).cancel(); TaskManager.tasks.remove(currentIndex); chunk.unload(true); return; @@ -272,7 +273,7 @@ public class ChunkListener implements Listener { int i = 0; while (System.currentTimeMillis() - start < 250) { if (i >= tiles.length - Settings.Chunk_Processor.MAX_TILES) { - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); + TaskManager.tasks.get(currentIndex).cancel(); TaskManager.tasks.remove(currentIndex); chunk.unload(true); return; @@ -280,7 +281,7 @@ public class ChunkListener implements Listener { tiles[i].getBlock().setType(Material.AIR, false); i++; } - }, 5); + }, TaskTime.ticks(5L)); TaskManager.tasks.put(currentIndex, task); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index ce868a61e..61e40742f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -111,6 +111,7 @@ import com.plotsquared.core.util.RegExUtil; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.world.block.BlockType; @@ -281,7 +282,7 @@ import java.util.regex.Pattern; ((BukkitPlayer) player).player.sendBlockChange(bloc, data); } } - }, 3); + }, TaskTime.ticks(3L)); } public static boolean checkEntity(Entity entity, Plot plot) { @@ -701,7 +702,7 @@ import java.util.regex.Pattern; player.saveData(); } this.eventDispatcher.doJoinTask(pp); - }, 20); + }, TaskTime.seconds(1L)); if (pp.hasPermission(Captions.PERMISSION_ADMIN_UPDATE_NOTIFICATION.getTranslated()) && Settings.Enabled_Components.UPDATE_NOTIFICATIONS && PremiumVerification.isPremium() diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java index cc5c1f72f..adb597202 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java @@ -26,7 +26,7 @@ package com.plotsquared.bukkit.queue; import com.google.common.base.Preconditions; -import com.plotsquared.bukkit.BukkitMain; +import com.plotsquared.bukkit.BukkitPlatform; import com.sk89q.worldedit.math.BlockVector2; import io.papermc.lib.PaperLib; import org.bukkit.Chunk; @@ -100,7 +100,7 @@ public final class ChunkCoordinator extends BukkitRunnable { this.maxIterationTime = maxIterationTime; this.whenDone = whenDone; this.throwableConsumer = throwableConsumer; - this.plugin = JavaPlugin.getPlugin(BukkitMain.class); + this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class); } /** diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java index 55dc45512..f9b0eb563 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java @@ -44,6 +44,7 @@ import com.plotsquared.core.util.RegionUtil; import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.math.BlockVector2; @@ -399,9 +400,9 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE; }); } if (!chunks.isEmpty()) { - TaskManager.runTaskLater(this, 1); + TaskManager.runTaskLater(this, TaskTime.ticks(1L)); } else { - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); } } }); @@ -456,7 +457,7 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE; PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(() -> { for (ContentMap map : maps) { map.restoreEntities(world1, 0, 0); - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); } }); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java deleted file mode 100644 index c5928c261..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.plotsquared.bukkit.util; - -import com.google.inject.Inject; -import com.google.inject.Singleton; -import com.plotsquared.bukkit.BukkitPlatform; -import com.plotsquared.core.util.task.TaskManager; -import org.bukkit.Bukkit; - -@Singleton public class BukkitTaskManager extends TaskManager { - - private final BukkitPlatform bukkitMain; - - @Inject public BukkitTaskManager(BukkitPlatform bukkitMain) { - this.bukkitMain = bukkitMain; - } - - @Override public int taskRepeat(Runnable runnable, int interval) { - return this.bukkitMain.getServer().getScheduler() - .scheduleSyncRepeatingTask(this.bukkitMain, runnable, interval, interval); - } - - @SuppressWarnings("deprecation") @Override - public int taskRepeatAsync(Runnable runnable, int interval) { - return this.bukkitMain.getServer().getScheduler() - .scheduleAsyncRepeatingTask(this.bukkitMain, runnable, interval, interval); - } - - @Override public void taskAsync(Runnable runnable) { - if (this.bukkitMain.isEnabled()) { - this.bukkitMain.getServer().getScheduler() - .runTaskAsynchronously(this.bukkitMain, runnable); - } else { - runnable.run(); - } - } - - @Override public void task(Runnable runnable) { - this.bukkitMain.getServer().getScheduler().runTask(this.bukkitMain, runnable).getTaskId(); - } - - @Override public void taskLater(Runnable runnable, int delay) { - this.bukkitMain.getServer().getScheduler().runTaskLater(this.bukkitMain, runnable, delay) - .getTaskId(); - } - - @Override public void taskLaterAsync(Runnable runnable, int delay) { - this.bukkitMain.getServer().getScheduler() - .runTaskLaterAsynchronously(this.bukkitMain, runnable, delay); - } - - @Override public void cancelTask(int task) { - if (task != -1) { - Bukkit.getScheduler().cancelTask(task); - } - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitPlotSquaredTask.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitPlotSquaredTask.java new file mode 100644 index 000000000..d6b2cc7bf --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitPlotSquaredTask.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.bukkit.util.task; + +import com.plotsquared.core.util.task.PlotSquaredTask; +import lombok.RequiredArgsConstructor; +import org.bukkit.scheduler.BukkitRunnable; + +import javax.annotation.Nonnull; + +/** + * Bukkit implementation of {@link PlotSquaredTask} + */ +@RequiredArgsConstructor +public final class BukkitPlotSquaredTask extends BukkitRunnable implements PlotSquaredTask { + + @Nonnull private final Runnable runnable; + + @Override public void runTask() { + this.runnable.run(); + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java new file mode 100644 index 000000000..dd1168ab0 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java @@ -0,0 +1,94 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.bukkit.util.task; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.core.util.task.PlotSquaredTask; +import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; + +import javax.annotation.Nonnull; + +/** + * Bukkit implementation of {@link TaskManager} using + * by {@link org.bukkit.scheduler.BukkitScheduler} and {@link BukkitPlotSquaredTask} + */ +@Singleton public class BukkitTaskManager extends TaskManager { + + private final BukkitPlatform bukkitMain; + private final TaskTime.TimeConverter timeConverter; + + @Inject public BukkitTaskManager(@Nonnull final BukkitPlatform bukkitMain, + @Nonnull final TaskTime.TimeConverter timeConverter) { + this.bukkitMain = bukkitMain; + this.timeConverter = timeConverter; + } + + @Override + public PlotSquaredTask taskRepeat(@Nonnull final Runnable runnable, + @Nonnull final TaskTime taskTime) { + final long ticks = this.timeConverter.toTicks(taskTime); + final BukkitPlotSquaredTask bukkitPlotSquaredTask = new BukkitPlotSquaredTask(runnable); + bukkitPlotSquaredTask.runTaskTimer(this.bukkitMain, ticks, ticks); + return bukkitPlotSquaredTask; + } + + @Override + public PlotSquaredTask taskRepeatAsync(@Nonnull final Runnable runnable, + @Nonnull final TaskTime taskTime) { + final long ticks = this.timeConverter.toTicks(taskTime); + final BukkitPlotSquaredTask bukkitPlotSquaredTask = new BukkitPlotSquaredTask(runnable); + bukkitPlotSquaredTask.runTaskTimerAsynchronously(this.bukkitMain, ticks, ticks); + return bukkitPlotSquaredTask; + } + + @Override public void taskAsync(@Nonnull final Runnable runnable) { + if (this.bukkitMain.isEnabled()) { + new BukkitPlotSquaredTask(runnable).runTaskAsynchronously(this.bukkitMain); + } else { + runnable.run(); + } + } + + @Override public void task(@Nonnull final Runnable runnable) { + new BukkitPlotSquaredTask(runnable).runTaskAsynchronously(this.bukkitMain); + } + + @Override public void taskLater(@Nonnull final Runnable runnable, + @Nonnull final TaskTime taskTime) { + final long delay = this.timeConverter.toTicks(taskTime); + new BukkitPlotSquaredTask(runnable).runTaskLater(this.bukkitMain, delay); + } + + @Override public void taskLaterAsync(@Nonnull final Runnable runnable, + @Nonnull final TaskTime taskTime) { + final long delay = this.timeConverter.toTicks(taskTime); + new BukkitPlotSquaredTask(runnable).runTaskLaterAsynchronously(this.bukkitMain, delay); + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java new file mode 100644 index 000000000..883708f5f --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java @@ -0,0 +1,47 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.bukkit.util.task; + +import com.plotsquared.core.util.task.TaskTime; +import org.bukkit.Bukkit; + +import javax.annotation.Nonnegative; + +/** + * Time converter that uses the server MSPT count to convert between + * different time units + */ +public final class PaperTimeConverter implements TaskTime.TimeConverter { + + @Override public long msToTicks(@Nonnegative final long ms) { + return (long) (ms / Bukkit.getAverageTickTime()); + } + + @Override public long ticksToMs(@Nonnegative final long ticks) { + return (long) (ticks * Bukkit.getAverageTickTime()); + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java new file mode 100644 index 000000000..86c9673d8 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java @@ -0,0 +1,47 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.bukkit.util.task; + +import com.plotsquared.core.util.task.TaskTime; + +import javax.annotation.Nonnegative; + +/** + * Naive time converter that assumes that all ticks are 50 milliseconds + */ +public final class SpigotTimeConverter implements TaskTime.TimeConverter { + + private static final long MS_PER_TICKS = 50L; + + @Override public long msToTicks(@Nonnegative final long ms) { + return ms / MS_PER_TICKS; + } + + @Override public long ticksToMs(@Nonnegative final long ticks) { + return ticks * MS_PER_TICKS; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java b/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java index f7096834b..c8aee497c 100644 --- a/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java +++ b/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java @@ -29,6 +29,7 @@ import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; public class CmdConfirm { @@ -46,11 +47,9 @@ public class CmdConfirm { if (commandStr != null) { MainUtil.sendMessage(player, Captions.REQUIRES_CONFIRM, commandStr); } - TaskManager.runTaskLater(new Runnable() { - @Override public void run() { - CmdInstance cmd = new CmdInstance(runnable); - player.setMeta("cmdConfirm", cmd); - } - }, 1); + TaskManager.runTaskLater(() -> { + CmdInstance cmd = new CmdInstance(runnable); + player.setMeta("cmdConfirm", cmd); + }, TaskTime.ticks(1L)); } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Condense.java b/Core/src/main/java/com/plotsquared/core/command/Condense.java index 180e26581..2b93b6839 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Condense.java +++ b/Core/src/main/java/com/plotsquared/core/command/Condense.java @@ -35,6 +35,8 @@ import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; + import javax.annotation.Nonnull; import java.util.ArrayList; @@ -177,7 +179,7 @@ public class Condense extends SubCommand { if (result.get()) { MainUtil.sendMessage(player, "Moving: " + origin + " -> " + possible); - TaskManager.runTaskLater(task, 1); + TaskManager.runTaskLater(task, TaskTime.ticks(1L)); } }, false).get()); } catch (InterruptedException | ExecutionException e) { diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index e2fdfde60..366609cb2 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -482,9 +482,9 @@ public class Settings extends Config { @Comment("Teleport to your plot on death") public static boolean ON_DEATH = false; @Comment("Teleport to your plot on login") public static boolean ON_LOGIN = false; @Comment("Teleport to your plot on claim") public static boolean ON_CLAIM = true; - @Comment({"Add a delay to all teleport commands", - "Assign `plots.teleport.delay.bypass` to bypass the cooldown."}) public static int - DELAY = 0; + @Comment({"Add a delay to all teleport commands (in seconds)", + "Assign `plots.teleport.delay.bypass` to bypass the cooldown"}) + public static int DELAY = 0; @Comment("The visit command is ordered by world instead of globally") public static boolean PER_WORLD_VISIT = false; } diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java index 30586db05..5da96f94b 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java @@ -54,6 +54,7 @@ import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; @@ -366,7 +367,7 @@ public class HybridUtils { analyzeRegion(origin.getWorldName(), region, new RunnableVal() { @Override public void run(PlotAnalysis value) { analysis.add(value); - TaskManager.runTaskLater(task, 1); + TaskManager.runTaskLater(task, TaskTime.ticks(1L)); } }); } @@ -511,7 +512,7 @@ public class HybridUtils { } } } - blockQueue.addEmptyTask(() -> TaskManager.runTaskLater(task, 20)); + blockQueue.addEmptyTask(() -> TaskManager.runTaskLater(task, TaskTime.seconds(1L))); }); } } diff --git a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java index f01253053..d534dfa4b 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -61,6 +61,7 @@ import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; @@ -125,7 +126,7 @@ public class PlotListener { } } } - }, 20); + }, TaskTime.seconds(1L)); } public boolean plotEntry(final PlotPlayer player, final Plot plot) { @@ -279,7 +280,7 @@ public class PlotListener { replacements); player.sendTitle(main, sub); } - }, 20); + }, TaskTime.seconds(1L)); } } diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 70f39aa08..6b5d9d723 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -66,6 +66,7 @@ import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.uuid.UUIDPipeline; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; @@ -1946,7 +1947,7 @@ public class Plot { this.getId().recalculateHash(); this.area.addPlotAbs(this); DBFunc.movePlot(this, plot); - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); return true; } @@ -2909,7 +2910,7 @@ public class Plot { this.plotListener.plotExit(pp, Plot.this); this.plotListener.plotEntry(pp, Plot.this); } - }, 1); + }, TaskTime.ticks(1L)); } public void debug(@Nonnull final String message) { @@ -3004,7 +3005,7 @@ public class Plot { MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT); player.teleport(location, cause); } - }, Settings.Teleport.DELAY * 20); + }, TaskTime.seconds(Settings.Teleport.DELAY)); resultConsumer.accept(true); }; if (this.area.isHomeAllowNonmember() || plot.isAdded(player.getUUID())) { @@ -3154,7 +3155,7 @@ public class Plot { final int offsetX = db.getX() - ob.getX(); final int offsetZ = db.getZ() - ob.getZ(); if (!this.hasOwner()) { - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); return CompletableFuture.completedFuture(false); } AtomicBoolean occupied = new AtomicBoolean(false); @@ -3163,7 +3164,7 @@ public class Plot { Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); if (other.hasOwner()) { if (!allowSwap) { - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); return CompletableFuture.completedFuture(false); } occupied.set(true); @@ -3270,14 +3271,14 @@ public class Plot { final int offsetX = db.getX() - ob.getX(); final int offsetZ = db.getZ() - ob.getZ(); if (!this.hasOwner()) { - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); return false; } Set plots = this.getConnectedPlots(); for (Plot plot : plots) { Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); if (other.hasOwner()) { - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); return false; } } diff --git a/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java b/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java index 141d729c7..c751fe54a 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java @@ -32,6 +32,7 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import java.util.Collection; import java.util.HashMap; @@ -72,7 +73,7 @@ import java.util.concurrent.atomic.AtomicInteger; } }); } - }, 20); + }, TaskTime.seconds(1L)); } public static long getTimestamp(PlotPlayer player, String inbox) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java index e805ff87a..af14ed3eb 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java @@ -43,15 +43,15 @@ import com.plotsquared.core.plot.flag.implementations.KeepFlag; import com.plotsquared.core.plot.message.PlotMessage; import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.MainUtil; -import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nonnull; +import javax.annotation.Nonnull; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -326,7 +326,8 @@ public class ExpireManager { } for (ExpiryTask expiryTask : expired) { if (!expiryTask.needsAnalysis()) { - expiredTask.run(newPlot, () -> TaskManager.getImplementation().taskLaterAsync(task, 1), + expiredTask.run(newPlot, () -> TaskManager.getImplementation() + .taskLaterAsync(task, TaskTime.ticks(1L)), expiryTask.requiresConfirmation()); return; } @@ -337,7 +338,7 @@ public class ExpireManager { passesComplexity(changed, expired, new RunnableVal() { @Override public void run(Boolean confirmation) { expiredTask.run(newPlot, - () -> TaskManager.getImplementation().taskLaterAsync(task, 1), + () -> TaskManager.getImplementation().taskLaterAsync(task, TaskTime.ticks(1L)), confirmation); } }, () -> { @@ -350,7 +351,7 @@ public class ExpireManager { return; } newPlot.setFlag(event.getFlag()); - TaskManager.runTaskLaterAsync(task, 20); + TaskManager.runTaskLaterAsync(task, TaskTime.seconds(1L)); }); } }; @@ -363,7 +364,7 @@ public class ExpireManager { @Override public void run(Boolean value) { doAnalysis.run(); } - }, () -> TaskManager.getImplementation().taskLaterAsync(task, 1)); + }, () -> TaskManager.getImplementation().taskLaterAsync(task, TaskTime.ticks(1L))); } else { doAnalysis.run(); } @@ -376,9 +377,9 @@ public class ExpireManager { ExpireManager.this.running = 2; runTask(expiredTask); } - }, 86400000); + }, TaskTime.ticks(86400000)); } else { - TaskManager.runTaskLaterAsync(task, 20 * 10); + TaskManager.runTaskLaterAsync(task, TaskTime.seconds(10L)); } } }); diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index 9f79102b0..1ef62a4eb 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -28,6 +28,7 @@ package com.plotsquared.core.queue; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import java.util.ArrayList; import java.util.ConcurrentModificationException; @@ -165,7 +166,7 @@ public class GlobalBlockQueue { SET_TASK.value2.endSet(true); } } - }, 1); + }, TaskTime.ticks(1L)); return true; } diff --git a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java index f9809840f..438f60940 100644 --- a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java @@ -32,6 +32,7 @@ import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.queue.ScopedLocalBlockQueue; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; @@ -172,7 +173,7 @@ public abstract class ChunkManager { task.run(); } if (!chunks.isEmpty()) { - TaskManager.runTaskLater(this, 1); + TaskManager.runTaskLater(this, TaskTime.ticks(1L)); } else { TaskManager.runTask(whenDone); } diff --git a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java index 7f933df24..fde4a7008 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java @@ -35,6 +35,7 @@ import com.plotsquared.core.plot.schematic.Schematic; import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntArrayTag; @@ -661,7 +662,7 @@ public abstract class SchematicHandler { zTask.run(); } if (yiter.hasNext()) { - TaskManager.runTaskLater(this, 1); + TaskManager.runTaskLater(this, TaskTime.ticks(1L)); } else { regionTask.run(); } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java b/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java index 63c0ebc8c..547541332 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java @@ -44,9 +44,9 @@ public class ObjectTaskRunnable implements Runnable { task.run(); } if (!hasNext) { - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); } else { - TaskManager.runTaskLater(this, 1); + TaskManager.runTaskLater(this, TaskTime.ticks(1L)); } } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/PlotSquaredTask.java b/Core/src/main/java/com/plotsquared/core/util/task/PlotSquaredTask.java new file mode 100644 index 000000000..3f1f9a16b --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/task/PlotSquaredTask.java @@ -0,0 +1,90 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.task; + +/** + * A task that can be run and cancelled (if repeating) + */ +public interface PlotSquaredTask extends Runnable { + + /** + * Run the task. Don't override this, instead + * implement {@link #runTask()} + */ + @Override default void run() { + if (isCancelled()) { + return; + } + this.runTask(); + } + + /** + * Run the task + */ + void runTask(); + + /** + * Check if the task has been cancelled + * + * @return {@code true} if the tasks is cancelled, + * {@code false} if not + */ + boolean isCancelled(); + + /** + * Cancel the task + */ + void cancel(); + + /** + * Get a new {@link NullTask} + * + * @return Null task instance + */ + static NullTask nullTask() { + return new NullTask(); + } + + + /** + * Task that does nothing and is always cancelled + */ + class NullTask implements PlotSquaredTask { + + @Override public void runTask() { + } + + @Override public boolean isCancelled() { + return true; + } + + @Override public void cancel() { + } + + } + +} + diff --git a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java index 0e2a923e2..e39d8182b 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java @@ -29,7 +29,10 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.util.RuntimeExceptionRunnableVal; import lombok.Getter; import lombok.Setter; +import org.jetbrains.annotations.NotNull; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -40,32 +43,55 @@ import java.util.concurrent.atomic.AtomicInteger; public abstract class TaskManager { public static final HashSet TELEPORT_QUEUE = new HashSet<>(); - public static final HashMap tasks = new HashMap<>(); + public static final HashMap tasks = new HashMap<>(); public static AtomicInteger index = new AtomicInteger(0); @Getter @Setter private static TaskManager implementation; - public static int runTaskRepeat(Runnable runnable, int interval) { + /** + * Run a repeating synchronous task. If using a platform scheduler, + * this is guaranteed to run on the server thread + * + * @param runnable Task to run + * @param taskTime Task interval + * @return Created task object, can be used to cancel the task + */ + @Nonnull public static PlotSquaredTask runTaskRepeat(@Nullable final Runnable runnable, + @Nonnull final TaskTime taskTime) { if (runnable != null) { if (getImplementation() == null) { throw new IllegalArgumentException("disabled"); } - return getImplementation().taskRepeat(runnable, interval); + return getImplementation().taskRepeat(runnable, taskTime); } - return -1; + return PlotSquaredTask.nullTask(); } - public static int runTaskRepeatAsync(Runnable runnable, int interval) { + /** + * Run a repeating asynchronous task. This will never run on the + * server thread + * + * @param runnable Task to run + * @param taskTime Task interval + * @return Created task object, can be used to cancel the task + */ + @Nonnull public static PlotSquaredTask runTaskRepeatAsync(@Nullable final Runnable runnable, + @NotNull final TaskTime taskTime) { if (runnable != null) { if (getImplementation() == null) { throw new IllegalArgumentException("disabled"); } - return getImplementation().taskRepeatAsync(runnable, interval); + return getImplementation().taskRepeatAsync(runnable, taskTime); } - return -1; + return PlotSquaredTask.nullTask(); } - public static void runTaskAsync(Runnable runnable) { + /** + * Run an asynchronous task. This will never run on the server thread + * + * @param runnable Task to run + */ + public static void runTaskAsync(@Nullable final Runnable runnable) { if (runnable != null) { if (getImplementation() == null) { runnable.run(); @@ -75,7 +101,13 @@ public abstract class TaskManager { } } - public static void runTask(Runnable runnable) { + /** + * Run a synchronous task. If using a platform scheduler, this is guaranteed + * to run on the server thread + * + * @param runnable Task to run + */ + public static void runTask(@Nullable final Runnable runnable) { if (runnable != null) { if (getImplementation() == null) { runnable.run(); @@ -86,37 +118,43 @@ public abstract class TaskManager { } /** - * Run task later. + * Run a synchronous task after a given delay. + * If using a platform scheduler, this is guaranteed to run on the server thread * - * @param runnable The task - * @param delay The delay in ticks + * @param runnable Task to run + * @param taskTime Task delay */ - public static void runTaskLater(Runnable runnable, int delay) { + public static void runTaskLater(@Nullable final Runnable runnable, + @Nonnull final TaskTime taskTime) { if (runnable != null) { if (getImplementation() == null) { runnable.run(); return; } - getImplementation().taskLater(runnable, delay); + getImplementation().taskLater(runnable, taskTime); } } - public static void runTaskLaterAsync(Runnable runnable, int delay) { + /** + * Run an asynchronous task after a given delay. This will never + * run on the server thread + * + * @param runnable Task to run + * @param taskTime Task delay + */ + public static void runTaskLaterAsync(@Nullable final Runnable runnable, + @Nonnull final TaskTime taskTime) { if (runnable != null) { if (getImplementation() == null) { runnable.run(); return; } - getImplementation().taskLaterAsync(runnable, delay); + getImplementation().taskLaterAsync(runnable, taskTime); } } /** * Break up a series of tasks so that they can run without lagging the server. - * - * @param objects - * @param task - * @param whenDone */ public static void objectTask(Collection objects, final RunnableVal task, final Runnable whenDone) { @@ -152,17 +190,61 @@ public abstract class TaskManager { return function.value; } - public abstract int taskRepeat(Runnable runnable, int interval); + /** + * Run a repeating synchronous task. If using a platform scheduler, + * this is guaranteed to run on the server thread + * + * @param runnable Task to run + * @param taskTime Task interval + * @return Created task object, can be used to cancel the task + */ + public abstract PlotSquaredTask taskRepeat(@Nonnull Runnable runnable, + @Nonnull TaskTime taskTime); - public abstract int taskRepeatAsync(Runnable runnable, int interval); + /** + * Run a repeating asynchronous task. This will never run on the + * server thread + * + * @param runnable Task to run + * @param taskTime Task interval + * @return Created task object, can be used to cancel the task + */ + public abstract PlotSquaredTask taskRepeatAsync(@Nonnull Runnable runnable, + @Nonnull TaskTime taskTime); - public abstract void taskAsync(Runnable runnable); + /** + * Run an asynchronous task. This will never run on the server thread + * + * @param runnable Task to run + */ + public abstract void taskAsync(@Nonnull Runnable runnable); - public abstract void task(Runnable runnable); + /** + * Run a synchronous task. If using a platform scheduler, this is guaranteed + * to run on the server thread + * + * @param runnable Task to run + */ + public abstract void task(@Nonnull Runnable runnable); - public abstract void taskLater(Runnable runnable, int delay); + /** + * Run a synchronous task after a given delay. + * If using a platform scheduler, this is guaranteed to run on the server thread + * + * @param runnable Task to run + * @param taskTime Task delay + */ + public abstract void taskLater(@Nonnull Runnable runnable, + @Nonnull TaskTime taskTime); - public abstract void taskLaterAsync(Runnable runnable, int delay); + /** + * Run an asynchronous task after a given delay. This will never + * run on the server thread + * + * @param runnable Task to run + * @param taskTime Task delay + */ + public abstract void taskLaterAsync(@Nonnull Runnable runnable, + @Nonnull TaskTime taskTime); - public abstract void cancelTask(int task); } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/TaskTime.java b/Core/src/main/java/com/plotsquared/core/util/task/TaskTime.java new file mode 100644 index 000000000..d11a0b111 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/task/TaskTime.java @@ -0,0 +1,150 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.task; + +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +/** + * Task timings + */ +@EqualsAndHashCode @ToString @SuppressWarnings("unused") +public final class TaskTime { + + private final long time; + private final TaskUnit unit; + + private TaskTime(@Nonnegative final long time, @Nonnull final TaskUnit unit) { + this.time = time; + this.unit = unit; + } + + /** + * Create a new task time in seconds + * + * @param seconds Seconds + * @return Created task time instance + */ + @Nonnull public static TaskTime seconds(@Nonnegative final long seconds) { + return new TaskTime(seconds * 1000L, TaskUnit.MILLISECONDS); + } + + /** + * Create a new task time in server ticks + * + * @param ticks Server ticks + * @return Created task time instance + */ + @Nonnull public static TaskTime ticks(@Nonnegative final long ticks) { + return new TaskTime(ticks, TaskUnit.TICKS); + } + + /** + * Create a new task time in milliseconds + * + * @param ms Milliseconds + * @return Created task time instance + */ + @Nonnull public static TaskTime ms(@Nonnegative final long ms) { + return new TaskTime(ms, TaskUnit.MILLISECONDS); + } + + /** + * Get the task time + * + * @return Task time + */ + @Nonnegative public long getTime() { + return this.time; + } + + /** + * Get the time unit + * + * @return Time unit + */ + @Nonnull public TaskUnit getUnit() { + return this.unit; + } + + + public enum TaskUnit { + TICKS, MILLISECONDS + } + + + public interface TimeConverter { + + /** + * Convert from milliseconds to server ticks + * + * @param ms Milliseconds + * @return Server ticks + */ + @Nonnegative long msToTicks(@Nonnegative final long ms); + + /** + * Convert from server ticks to milliseconds + * + * @param ticks Server ticks + * @return Milliseconds + */ + @Nonnegative long ticksToMs(@Nonnegative final long ticks); + + /** + * Convert the task time to server ticks + * + * @param taskTime Task time + * @return Server ticks + */ + @Nonnegative default long toTicks(@Nonnull final TaskTime taskTime) { + if (taskTime.getUnit() == TaskUnit.TICKS) { + return taskTime.getTime(); + } else { + return this.msToTicks(taskTime.getTime()); + } + } + + /** + * Convert the task time to milliseconds + * + * @param taskTime Task time + * @return Milliseconds + */ + @Nonnegative default long toMs(@Nonnull final TaskTime taskTime) { + if (taskTime.getUnit() == TaskUnit.MILLISECONDS) { + return taskTime.getTime(); + } else { + return this.ticksToMs(taskTime.getTime()); + } + } + + } + +} From 5a3eacde0b1f92bd8dfbcd25a61db8d3a8017f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 17 Jul 2020 16:25:57 +0200 Subject: [PATCH 2/5] Replace method synchronization logic --- .../plotsquared/bukkit/util/BukkitUtil.java | 20 ++-- .../bukkit/util/task/BukkitTaskManager.java | 8 ++ .../com/plotsquared/core/command/Auto.java | 10 +- .../com/plotsquared/core/command/Claim.java | 57 +++++----- .../core/generator/HybridUtils.java | 25 ++--- .../core/plot/world/SinglePlotArea.java | 22 ++-- .../core/queue/BasicLocalBlockQueue.java | 14 ++- .../core/util/task/AutoClaimFinishTask.java | 10 +- .../core/util/task/TaskManager.java | 103 +++++++++--------- 9 files changed, 144 insertions(+), 125 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index f25fdc621..5864b528e 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -42,7 +42,6 @@ import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; @@ -54,7 +53,6 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import io.papermc.lib.PaperLib; - import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Material; @@ -96,11 +94,11 @@ import org.bukkit.entity.Snowman; import org.bukkit.entity.Tameable; import org.bukkit.entity.Vehicle; import org.bukkit.entity.WaterMob; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -423,14 +421,18 @@ import java.util.stream.Stream; @Override @Nullable public String[] getSignSynchronous(@Nonnull final Location location) { Block block = getWorld(location.getWorldName()) .getBlockAt(location.getX(), location.getY(), location.getZ()); - return TaskManager.getImplementation().sync(new RunnableVal() { - @Override public void run(String[] value) { + try { + return TaskManager.getImplementation().sync(() -> { if (block.getState() instanceof Sign) { Sign sign = (Sign) block.getState(); - this.value = sign.getLines(); + return sign.getLines(); } - } - }); + return new String[0]; + }); + } catch (final Exception e) { + e.printStackTrace(); + } + return new String[0]; } @Override public Location getSpawn(@Nonnull final String world) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java index dd1168ab0..a8d054fc9 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java @@ -31,8 +31,12 @@ import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.core.util.task.PlotSquaredTask; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskTime; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; /** * Bukkit implementation of {@link TaskManager} using @@ -75,6 +79,10 @@ import javax.annotation.Nonnull; } } + @Override public Future callMethodSync(@NotNull final Callable method) { + return Bukkit.getScheduler().callSyncMethod(this.bukkitMain, method); + } + @Override public void task(@Nonnull final Runnable runnable) { new BukkitPlotSquaredTask(runnable).runTaskAsynchronously(this.bukkitMain); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Auto.java b/Core/src/main/java/com/plotsquared/core/command/Auto.java index e212d3e58..adfb04ef6 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Auto.java +++ b/Core/src/main/java/com/plotsquared/core/command/Auto.java @@ -147,13 +147,17 @@ public class Auto extends SubCommand { * @param start * @param schematic */ - public static void autoClaimSafe(final PlotPlayer player, final PlotArea area, PlotId start, + public static void autoClaimSafe(final PlotPlayer player, final PlotArea area, PlotId start, final String schematic) { player.setMeta(Auto.class.getName(), true); autoClaimFromDatabase(player, area, start, new RunnableVal() { @Override public void run(final Plot plot) { - TaskManager.getImplementation().sync(new AutoClaimFinishTask(player, plot, area, schematic, - PlotSquared.get().getEventDispatcher())); + try { + TaskManager.getImplementation().sync(new AutoClaimFinishTask(player, plot, area, schematic, + PlotSquared.get().getEventDispatcher())); + } catch (final Exception e) { + e.printStackTrace(); + } } }); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Claim.java b/Core/src/main/java/com/plotsquared/core/command/Claim.java index 7b51ea6cf..f698bdc10 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Claim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Claim.java @@ -27,7 +27,6 @@ package com.plotsquared.core.command; import com.google.common.primitives.Ints; import com.google.inject.Inject; -import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; @@ -44,29 +43,24 @@ import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.Expression; import com.plotsquared.core.util.Permissions; -import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@CommandDeclaration(command = "claim", - aliases = "c", - description = "Claim the current plot you're standing on", - category = CommandCategory.CLAIMING, - requiredType = RequiredType.PLAYER, - permission = "plots.claim", - usage = "/plot claim") +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +@CommandDeclaration(command = "claim", aliases = "c", description = "Claim the current plot you're standing on", category = CommandCategory.CLAIMING, requiredType = RequiredType.PLAYER, permission = "plots.claim", usage = "/plot claim") public class Claim extends SubCommand { - private static final Logger logger = LoggerFactory.getLogger("P2/" + Claim.class.getSimpleName()); + private static final Logger logger = + LoggerFactory.getLogger("P2/" + Claim.class.getSimpleName()); private final EventDispatcher eventDispatcher; private final EconHandler econHandler; @Inject public Claim(@Nonnull final EventDispatcher eventDispatcher, - @Nullable final EconHandler econHandler) { + @Nullable final EconHandler econHandler) { this.eventDispatcher = eventDispatcher; this.econHandler = econHandler; } @@ -146,24 +140,29 @@ public class Claim extends SubCommand { } plot.setOwnerAbs(player.getUUID()); final String finalSchematic = schematic; - DBFunc.createPlotSafe(plot, () -> TaskManager.getImplementation().sync(new RunnableVal() { - @Override public void run(Object value) { - if (!plot.claim(player, true, finalSchematic, false)) { - logger.info(Captions.PREFIX.getTranslated() + String - .format("Failed to claim plot %s", plot.getId().toCommaSeparatedString())); - sendMessage(player, Captions.PLOT_NOT_CLAIMED); - plot.setOwnerAbs(null); - } else if (area.isAutoMerge()) { - PlotMergeEvent event = Claim.this.eventDispatcher - .callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player); - if (event.getEventResult() == Result.DENY) { - sendMessage(player, Captions.EVENT_DENIED, "Auto merge on claim"); - } else { - plot.autoMerge(event.getDir(), event.getMax(), player.getUUID(), true); + DBFunc.createPlotSafe(plot, () -> { + try { + TaskManager.getImplementation().sync(() -> { + if (!plot.claim(player, true, finalSchematic, false)) { + logger.info(Captions.PREFIX.getTranslated() + String + .format("Failed to claim plot %s", plot.getId().toCommaSeparatedString())); + sendMessage(player, Captions.PLOT_NOT_CLAIMED); + plot.setOwnerAbs(null); + } else if (area.isAutoMerge()) { + PlotMergeEvent mergeEvent = Claim.this.eventDispatcher + .callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player); + if (mergeEvent.getEventResult() == Result.DENY) { + sendMessage(player, Captions.EVENT_DENIED, "Auto merge on claim"); + } else { + plot.autoMerge(mergeEvent.getDir(), mergeEvent.getMax(), player.getUUID(), true); + } } - } + return null; + }); + } catch (final Exception e) { + e.printStackTrace(); } - }), () -> { + }, () -> { logger.info(Captions.PREFIX.getTranslated() + String .format("Failed to add plot %s to the database", plot.getId().toCommaSeparatedString())); diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java index 5da96f94b..3846e9e72 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java @@ -479,21 +479,20 @@ public class HybridUtils { } } if (!chunks.isEmpty()) { - TaskManager.getImplementation().sync(new RunnableVal() { - @Override public void run(Object value) { - long start = System.currentTimeMillis(); - Iterator iterator = chunks.iterator(); - while (System.currentTimeMillis() - start < 20 && !chunks - .isEmpty()) { - final BlockVector2 chunk = iterator.next(); - iterator.remove(); - boolean regenedRoads = - regenerateRoad(area, chunk, extend); - if (!regenedRoads && Settings.DEBUG) { - logger.info("[P2] Failed to regenerate road"); - } + TaskManager.getImplementation().sync(() -> { + long start = System.currentTimeMillis(); + Iterator iterator = chunks.iterator(); + while (System.currentTimeMillis() - start < 20 && !chunks + .isEmpty()) { + final BlockVector2 chunk = iterator.next(); + iterator.remove(); + boolean regenedRoads = + regenerateRoad(area, chunk, extend); + if (!regenedRoads && Settings.DEBUG) { + logger.info("[P2] Failed to regenerate road"); } } + return null; }); } } catch (Exception e) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java index a7dcd8f22..ecda867bc 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java @@ -47,11 +47,10 @@ import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.setup.SettingsNodesWrapper; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.EventDispatcher; -import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; + import javax.annotation.Nonnull; import javax.annotation.Nullable; - import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -141,15 +140,18 @@ public class SinglePlotArea extends GridPlotWorld { } } - TaskManager.getImplementation().sync(new RunnableVal() { - @Override public void run(Object value) { - String worldName = id.getX() + "." + id.getY(); - if (PlotSquared.platform().getWorldUtil().isWorld(worldName)) { - return; + try { + TaskManager.getImplementation().sync(() -> { + final String name = id.getX() + "." + id.getY(); + if (!PlotSquared.platform().getWorldUtil().isWorld(name)) { + PlotSquared.platform().getSetupUtils().setupWorld(builder); } - PlotSquared.platform().getSetupUtils().setupWorld(builder); - } - }); + return null; + }); + } catch (final Exception e) { + e.printStackTrace(); + } + // String worldName = plot.getWorldName(); // World world = Bukkit.getWorld(worldName); // if (world != null) { diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java index e2bdd37e6..a5d0734c5 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java @@ -28,14 +28,13 @@ package com.plotsquared.core.queue; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.PatternUtil; -import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import javax.annotation.Nonnull; +import javax.annotation.Nonnull; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ExecutionException; @@ -185,12 +184,15 @@ public abstract class BasicLocalBlockQueue extends LocalBlockQueue { @Override public void flush() { this.globalBlockQueue.dequeue(this); - TaskManager.getImplementation().sync(new RunnableVal() { - @Override public void run(Object value) { + try { + TaskManager.getImplementation().sync(() -> { while (next()) { } - } - }); + return null; + }); + } catch (final Exception e) { + e.printStackTrace(); + } } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java b/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java index 1ac9c81e8..cdcdee0e7 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java @@ -36,10 +36,12 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.util.EventDispatcher; import lombok.RequiredArgsConstructor; +import java.util.concurrent.Callable; + import static com.plotsquared.core.util.MainUtil.sendMessage; @RequiredArgsConstructor -public final class AutoClaimFinishTask extends RunnableVal { +public final class AutoClaimFinishTask implements Callable { private final PlotPlayer player; private final Plot plot; @@ -47,11 +49,11 @@ public final class AutoClaimFinishTask extends RunnableVal { private final String schematic; private final EventDispatcher eventDispatcher; - @Override public void run(Object value) { + @Override public Boolean call() { player.deleteMeta(Auto.class.getName()); if (plot == null) { sendMessage(player, Captions.NO_FREE_PLOTS); - return; + return false; } plot.claim(player, true, schematic, false); if (area.isAutoMerge()) { @@ -62,5 +64,7 @@ public final class AutoClaimFinishTask extends RunnableVal { plot.autoMerge(event.getDir(), event.getMax(), player.getUUID(), true); } } + return true; } + } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java index e39d8182b..629057583 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java @@ -26,20 +26,30 @@ package com.plotsquared.core.util.task; import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.util.RuntimeExceptionRunnableVal; import lombok.Getter; import lombok.Setter; -import org.jetbrains.annotations.NotNull; +import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +/** + * Task manager that handles scheduling of tasks. + * Synchronous methods make no guarantee of being scheduled on the + * server thread, instead they guarantee that no two synchronous + * operations happen at the same time. Implementations of + * the task manager might make other guarantees. All asynchronous + * operations will happen on another thread, no matter where + * they're scheduled from. + */ public abstract class TaskManager { public static final HashSet TELEPORT_QUEUE = new HashSet<>(); @@ -57,7 +67,7 @@ public abstract class TaskManager { * @return Created task object, can be used to cancel the task */ @Nonnull public static PlotSquaredTask runTaskRepeat(@Nullable final Runnable runnable, - @Nonnull final TaskTime taskTime) { + @Nonnull final TaskTime taskTime) { if (runnable != null) { if (getImplementation() == null) { throw new IllegalArgumentException("disabled"); @@ -67,25 +77,6 @@ public abstract class TaskManager { return PlotSquaredTask.nullTask(); } - /** - * Run a repeating asynchronous task. This will never run on the - * server thread - * - * @param runnable Task to run - * @param taskTime Task interval - * @return Created task object, can be used to cancel the task - */ - @Nonnull public static PlotSquaredTask runTaskRepeatAsync(@Nullable final Runnable runnable, - @NotNull final TaskTime taskTime) { - if (runnable != null) { - if (getImplementation() == null) { - throw new IllegalArgumentException("disabled"); - } - return getImplementation().taskRepeatAsync(runnable, taskTime); - } - return PlotSquaredTask.nullTask(); - } - /** * Run an asynchronous task. This will never run on the server thread * @@ -125,7 +116,7 @@ public abstract class TaskManager { * @param taskTime Task delay */ public static void runTaskLater(@Nullable final Runnable runnable, - @Nonnull final TaskTime taskTime) { + @Nonnull final TaskTime taskTime) { if (runnable != null) { if (getImplementation() == null) { runnable.run(); @@ -143,7 +134,7 @@ public abstract class TaskManager { * @param taskTime Task delay */ public static void runTaskLaterAsync(@Nullable final Runnable runnable, - @Nonnull final TaskTime taskTime) { + @Nonnull final TaskTime taskTime) { if (runnable != null) { if (getImplementation() == null) { runnable.run(); @@ -162,34 +153,44 @@ public abstract class TaskManager { TaskManager.runTask(new ObjectTaskRunnable<>(iterator, task, whenDone)); } - public T sync(final RunnableVal function) { + /** + * Make a synchronous method call and return the result + * + * @param function Method to call + * @param Return type + * @return Method result + * @throws Exception If the call fails + */ + public T sync(final Callable function) throws Exception { return sync(function, Integer.MAX_VALUE); } - public T sync(final RunnableVal function, int timeout) { + /** + * Make a synchronous method call and return the result + * + * @param function Method to call + * @param timeout Timeout (ms) + * @param Return type + * @return Method result + * @throws Exception If the call fails + */ + public T sync(final Callable function, int timeout) throws Exception { if (PlotSquared.get().isMainThread(Thread.currentThread())) { - function.run(); - return function.value; + return function.call(); } - final AtomicBoolean running = new AtomicBoolean(true); - final RuntimeExceptionRunnableVal run = - new RuntimeExceptionRunnableVal<>(function, running); - TaskManager.getImplementation().task(run); - try { - synchronized (function) { - while (running.get()) { - function.wait(timeout); - } - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (run.value != null) { - throw run.value; - } - return function.value; + return this.callMethodSync(function).get(timeout, TimeUnit.MILLISECONDS); } + /** + * Call a method synchronously and return a future with + * the result of the result + * + * @param method Method to be ran synchronously + * @param Return type + * @return Future completing with the result + */ + public abstract Future callMethodSync(@Nonnegative final Callable method); + /** * Run a repeating synchronous task. If using a platform scheduler, * this is guaranteed to run on the server thread @@ -199,7 +200,7 @@ public abstract class TaskManager { * @return Created task object, can be used to cancel the task */ public abstract PlotSquaredTask taskRepeat(@Nonnull Runnable runnable, - @Nonnull TaskTime taskTime); + @Nonnull TaskTime taskTime); /** * Run a repeating asynchronous task. This will never run on the @@ -210,7 +211,7 @@ public abstract class TaskManager { * @return Created task object, can be used to cancel the task */ public abstract PlotSquaredTask taskRepeatAsync(@Nonnull Runnable runnable, - @Nonnull TaskTime taskTime); + @Nonnull TaskTime taskTime); /** * Run an asynchronous task. This will never run on the server thread @@ -234,8 +235,7 @@ public abstract class TaskManager { * @param runnable Task to run * @param taskTime Task delay */ - public abstract void taskLater(@Nonnull Runnable runnable, - @Nonnull TaskTime taskTime); + public abstract void taskLater(@Nonnull Runnable runnable, @Nonnull TaskTime taskTime); /** * Run an asynchronous task after a given delay. This will never @@ -244,7 +244,6 @@ public abstract class TaskManager { * @param runnable Task to run * @param taskTime Task delay */ - public abstract void taskLaterAsync(@Nonnull Runnable runnable, - @Nonnull TaskTime taskTime); + public abstract void taskLaterAsync(@Nonnull Runnable runnable, @Nonnull TaskTime taskTime); } From 020b030667cf3d8090dfb3e2f8e63c9f8254041f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 17 Jul 2020 16:38:07 +0200 Subject: [PATCH 3/5] More fixes --- .../plotsquared/bukkit/BukkitPlatform.java | 4 +- .../plotsquared/bukkit/util/BukkitUtil.java | 2 +- .../bukkit/util/task/BukkitTaskManager.java | 9 ++++ .../com/plotsquared/core/command/Auto.java | 2 +- .../com/plotsquared/core/command/Claim.java | 2 +- .../plotsquared/core/command/DebugExec.java | 2 +- .../plotsquared/core/command/PluginCmd.java | 2 +- .../com/plotsquared/core/command/Trim.java | 11 ++-- .../core/generator/HybridUtils.java | 3 +- .../core/plot/expiration/ExpireManager.java | 6 +-- .../core/plot/world/SinglePlotArea.java | 2 +- .../core/plot/world/SinglePlotManager.java | 2 +- .../core/queue/BasicLocalBlockQueue.java | 2 +- .../plotsquared/core/util/RegionManager.java | 6 ++- .../core/util/task/ObjectTaskRunnable.java | 7 ++- .../core/util/task/TaskManager.java | 50 ++++++++++--------- 16 files changed, 65 insertions(+), 47 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java index 256736ff7..cf236b3e4 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java @@ -227,7 +227,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass; // Stuff that needs to be created before the PlotSquared instance PlotPlayer.registerConverter(Player.class, BukkitUtil::getPlayer); - TaskManager.setImplementation(new BukkitTaskManager(this, timeConverter)); + TaskManager.setPlatformImplementation(new BukkitTaskManager(this, timeConverter)); final PlotSquared plotSquared = new PlotSquared(this, "Bukkit"); @@ -510,7 +510,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass; this.startMetrics(); if (Settings.Enabled_Components.WORLDS) { - TaskManager.getImplementation().taskRepeat(this::unload, TaskTime.seconds(1L)); + TaskManager.getPlatformImplementation().taskRepeat(this::unload, TaskTime.seconds(1L)); try { singleWorldListener = getInjector().getInstance(SingleWorldListener.class); } catch (Exception e) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 5864b528e..75ac9a1be 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -422,7 +422,7 @@ import java.util.stream.Stream; Block block = getWorld(location.getWorldName()) .getBlockAt(location.getX(), location.getY(), location.getZ()); try { - return TaskManager.getImplementation().sync(() -> { + return TaskManager.getPlatformImplementation().sync(() -> { if (block.getState() instanceof Sign) { Sign sign = (Sign) block.getState(); return sign.getLines(); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java index a8d054fc9..643c4d8f3 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java @@ -28,6 +28,7 @@ package com.plotsquared.bukkit.util.task; import com.google.inject.Inject; import com.google.inject.Singleton; import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.util.task.PlotSquaredTask; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskTime; @@ -37,6 +38,7 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import java.util.concurrent.Callable; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; /** * Bukkit implementation of {@link TaskManager} using @@ -79,6 +81,13 @@ import java.util.concurrent.Future; } } + @Override public T sync(@Nonnull final Callable function, final int timeout) throws Exception { + if (PlotSquared.get().isMainThread(Thread.currentThread())) { + return function.call(); + } + return this.callMethodSync(function).get(timeout, TimeUnit.MILLISECONDS); + } + @Override public Future callMethodSync(@NotNull final Callable method) { return Bukkit.getScheduler().callSyncMethod(this.bukkitMain, method); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Auto.java b/Core/src/main/java/com/plotsquared/core/command/Auto.java index adfb04ef6..2c2f051e9 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Auto.java +++ b/Core/src/main/java/com/plotsquared/core/command/Auto.java @@ -153,7 +153,7 @@ public class Auto extends SubCommand { autoClaimFromDatabase(player, area, start, new RunnableVal() { @Override public void run(final Plot plot) { try { - TaskManager.getImplementation().sync(new AutoClaimFinishTask(player, plot, area, schematic, + TaskManager.getPlatformImplementation().sync(new AutoClaimFinishTask(player, plot, area, schematic, PlotSquared.get().getEventDispatcher())); } catch (final Exception e) { e.printStackTrace(); diff --git a/Core/src/main/java/com/plotsquared/core/command/Claim.java b/Core/src/main/java/com/plotsquared/core/command/Claim.java index f698bdc10..bb3ae02c3 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Claim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Claim.java @@ -142,7 +142,7 @@ public class Claim extends SubCommand { final String finalSchematic = schematic; DBFunc.createPlotSafe(plot, () -> { try { - TaskManager.getImplementation().sync(() -> { + TaskManager.getPlatformImplementation().sync(() -> { if (!plot.claim(player, true, finalSchematic, false)) { logger.info(Captions.PREFIX.getTranslated() + String .format("Failed to claim plot %s", plot.getId().toCommaSeparatedString())); diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java index 387320ffb..dbe3a526f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java @@ -182,7 +182,7 @@ public class DebugExec extends SubCommand { if (this.worldEdit != null) { this.scope.put("WEManager", new WEManager()); } - this.scope.put("TaskManager", TaskManager.getImplementation()); + this.scope.put("TaskManager", TaskManager.getPlatformImplementation()); this.scope.put("ConsolePlayer", ConsolePlayer.getConsole()); this.scope.put("SchematicHandler", this.schematicHandler); this.scope.put("ChunkManager", this.chunkManager); diff --git a/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java b/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java index 60925ccbd..f4069bec1 100644 --- a/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java @@ -40,7 +40,7 @@ import com.plotsquared.core.util.task.TaskManager; public class PluginCmd extends SubCommand { @Override public boolean onCommand(final PlotPlayer player, String[] args) { - TaskManager.getImplementation().taskAsync(() -> { + TaskManager.getPlatformImplementation().taskAsync(() -> { MainUtil.sendMessage(player, String.format( "$2>> $1&l" + PlotSquared.platform().getPluginName() + " $2($1Version$2: $1%s$2)", PlotSquared.get().getVersion())); diff --git a/Core/src/main/java/com/plotsquared/core/command/Trim.java b/Core/src/main/java/com/plotsquared/core/command/Trim.java index abdfb0a23..18aa48475 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Trim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Trim.java @@ -43,6 +43,7 @@ import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; import org.slf4j.Logger; @@ -102,7 +103,7 @@ public class Trim extends SubCommand { MainUtil.sendMessage(null, " - MCA #: " + result.value1.size()); MainUtil.sendMessage(null, " - CHUNKS: " + (result.value1.size() * 1024) + " (max)"); MainUtil.sendMessage(null, " - TIME ESTIMATE: 12 Parsecs"); - TaskManager.objectTask(plots, new RunnableVal() { + TaskManager.getPlatformImplementation().objectTask(plots, new RunnableVal() { @Override public void run(Plot plot) { Location pos1 = plot.getCorners()[0]; Location pos2 = plot.getCorners()[1]; @@ -119,7 +120,8 @@ public class Trim extends SubCommand { } } } - }, result); + }).thenAccept(ignore -> + TaskManager.getPlatformImplementation().taskLater(result, TaskTime.ticks(1))); return true; } @@ -189,11 +191,12 @@ public class Trim extends SubCommand { } } final LocalBlockQueue queue = blockQueue.getNewQueue(world, false); - TaskManager.objectTask(chunks, new RunnableVal() { + TaskManager.getPlatformImplementation().objectTask(chunks, new RunnableVal() { @Override public void run(BlockVector2 value) { queue.regenChunk(value.getX(), value.getZ()); } - }, this); + }).thenAccept(ignore -> TaskManager.getPlatformImplementation() + .taskLater(this, TaskTime.ticks(1))); } }; } else { diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java index 3846e9e72..ba1fc503b 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java @@ -26,7 +26,6 @@ package com.plotsquared.core.generator; import com.google.inject.Inject; -import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.events.PlotFlagAddEvent; import com.plotsquared.core.events.Result; @@ -479,7 +478,7 @@ public class HybridUtils { } } if (!chunks.isEmpty()) { - TaskManager.getImplementation().sync(() -> { + TaskManager.getPlatformImplementation().sync(() -> { long start = System.currentTimeMillis(); Iterator iterator = chunks.iterator(); while (System.currentTimeMillis() - start < 20 && !chunks diff --git a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java index af14ed3eb..0835ba8b1 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java @@ -326,7 +326,7 @@ public class ExpireManager { } for (ExpiryTask expiryTask : expired) { if (!expiryTask.needsAnalysis()) { - expiredTask.run(newPlot, () -> TaskManager.getImplementation() + expiredTask.run(newPlot, () -> TaskManager.getPlatformImplementation() .taskLaterAsync(task, TaskTime.ticks(1L)), expiryTask.requiresConfirmation()); return; @@ -338,7 +338,7 @@ public class ExpireManager { passesComplexity(changed, expired, new RunnableVal() { @Override public void run(Boolean confirmation) { expiredTask.run(newPlot, - () -> TaskManager.getImplementation().taskLaterAsync(task, TaskTime.ticks(1L)), + () -> TaskManager.getPlatformImplementation().taskLaterAsync(task, TaskTime.ticks(1L)), confirmation); } }, () -> { @@ -364,7 +364,7 @@ public class ExpireManager { @Override public void run(Boolean value) { doAnalysis.run(); } - }, () -> TaskManager.getImplementation().taskLaterAsync(task, TaskTime.ticks(1L))); + }, () -> TaskManager.getPlatformImplementation().taskLaterAsync(task, TaskTime.ticks(1L))); } else { doAnalysis.run(); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java index ecda867bc..0d29a8714 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java @@ -141,7 +141,7 @@ public class SinglePlotArea extends GridPlotWorld { } try { - TaskManager.getImplementation().sync(() -> { + TaskManager.getPlatformImplementation().sync(() -> { final String name = id.getX() + "." + id.getY(); if (!PlotSquared.platform().getWorldUtil().isWorld(name)) { PlotSquared.platform().getSetupUtils().setupWorld(builder); diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java index 096f3f6c8..a386022a3 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java @@ -64,7 +64,7 @@ public class SinglePlotManager extends PlotManager { @Override public boolean clearPlot(Plot plot, final Runnable whenDone) { PlotSquared.platform().getSetupUtils().unload(plot.getWorldName(), false); final File worldFolder = new File(PlotSquared.platform().getWorldContainer(), plot.getWorldName()); - TaskManager.getImplementation().taskAsync(() -> { + TaskManager.getPlatformImplementation().taskAsync(() -> { MainUtil.deleteDirectory(worldFolder); if (whenDone != null) { whenDone.run(); diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java index a5d0734c5..03aa8b437 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java @@ -185,7 +185,7 @@ public abstract class BasicLocalBlockQueue extends LocalBlockQueue { @Override public void flush() { this.globalBlockQueue.dequeue(this); try { - TaskManager.getImplementation().sync(() -> { + TaskManager.getPlatformImplementation().sync(() -> { while (next()) { } return null; diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java index 743395523..3afb51724 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java @@ -33,6 +33,7 @@ import com.plotsquared.core.plot.PlotManager; import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; @@ -94,12 +95,13 @@ public abstract class RegionManager { } } } - TaskManager.objectTask(chunks, new RunnableVal() { + TaskManager.getPlatformImplementation().objectTask(chunks, new RunnableVal() { @Override public void run(BlockVector2 value) { chunkManager.loadChunk(world, value, false) .thenRun(() -> task.run(value)); } - }, whenDone); + }).thenAccept(ignore -> + TaskManager.getPlatformImplementation().taskLater(whenDone, TaskTime.ticks(1))); }); } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java b/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java index 547541332..d9201ffac 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java @@ -25,16 +25,19 @@ */ package com.plotsquared.core.util.task; +import lombok.Getter; import lombok.RequiredArgsConstructor; import java.util.Iterator; +import java.util.concurrent.CompletableFuture; @RequiredArgsConstructor public class ObjectTaskRunnable implements Runnable { + @Getter private final CompletableFuture completionFuture = new CompletableFuture<>(); + private final Iterator iterator; private final RunnableVal task; - private final Runnable whenDone; @Override public void run() { long start = System.currentTimeMillis(); @@ -44,7 +47,7 @@ public class ObjectTaskRunnable implements Runnable { task.run(); } if (!hasNext) { - TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); + completionFuture.complete(null); } else { TaskManager.runTaskLater(this, TaskTime.ticks(1L)); } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java index 629057583..fdc04b620 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java @@ -25,7 +25,6 @@ */ package com.plotsquared.core.util.task; -import com.plotsquared.core.PlotSquared; import lombok.Getter; import lombok.Setter; @@ -37,8 +36,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** @@ -56,7 +55,7 @@ public abstract class TaskManager { public static final HashMap tasks = new HashMap<>(); public static AtomicInteger index = new AtomicInteger(0); - @Getter @Setter private static TaskManager implementation; + @Getter @Setter private static TaskManager platformImplementation; /** * Run a repeating synchronous task. If using a platform scheduler, @@ -69,10 +68,10 @@ public abstract class TaskManager { @Nonnull public static PlotSquaredTask runTaskRepeat(@Nullable final Runnable runnable, @Nonnull final TaskTime taskTime) { if (runnable != null) { - if (getImplementation() == null) { + if (getPlatformImplementation() == null) { throw new IllegalArgumentException("disabled"); } - return getImplementation().taskRepeat(runnable, taskTime); + return getPlatformImplementation().taskRepeat(runnable, taskTime); } return PlotSquaredTask.nullTask(); } @@ -84,11 +83,11 @@ public abstract class TaskManager { */ public static void runTaskAsync(@Nullable final Runnable runnable) { if (runnable != null) { - if (getImplementation() == null) { + if (getPlatformImplementation() == null) { runnable.run(); return; } - getImplementation().taskAsync(runnable); + getPlatformImplementation().taskAsync(runnable); } } @@ -100,11 +99,11 @@ public abstract class TaskManager { */ public static void runTask(@Nullable final Runnable runnable) { if (runnable != null) { - if (getImplementation() == null) { + if (getPlatformImplementation() == null) { runnable.run(); return; } - getImplementation().task(runnable); + getPlatformImplementation().task(runnable); } } @@ -118,11 +117,11 @@ public abstract class TaskManager { public static void runTaskLater(@Nullable final Runnable runnable, @Nonnull final TaskTime taskTime) { if (runnable != null) { - if (getImplementation() == null) { + if (getPlatformImplementation() == null) { runnable.run(); return; } - getImplementation().taskLater(runnable, taskTime); + getPlatformImplementation().taskLater(runnable, taskTime); } } @@ -136,21 +135,28 @@ public abstract class TaskManager { public static void runTaskLaterAsync(@Nullable final Runnable runnable, @Nonnull final TaskTime taskTime) { if (runnable != null) { - if (getImplementation() == null) { + if (getPlatformImplementation() == null) { runnable.run(); return; } - getImplementation().taskLaterAsync(runnable, taskTime); + getPlatformImplementation().taskLaterAsync(runnable, taskTime); } } /** - * Break up a series of tasks so that they can run without lagging the server. + * Break up a series of tasks so that they can run without lagging the server + * + * @param objects Objects to perform the task on + * @param task Task to perform + * @param Object type + * @return Future that completes when the tasks are done */ - public static void objectTask(Collection objects, final RunnableVal task, - final Runnable whenDone) { + public CompletableFuture objectTask(@Nonnull final Collection objects, + @Nonnull final RunnableVal task) { final Iterator iterator = objects.iterator(); - TaskManager.runTask(new ObjectTaskRunnable<>(iterator, task, whenDone)); + final ObjectTaskRunnable taskRunnable = new ObjectTaskRunnable<>(iterator, task); + TaskManager.runTask(taskRunnable); + return taskRunnable.getCompletionFuture(); } /** @@ -161,7 +167,7 @@ public abstract class TaskManager { * @return Method result * @throws Exception If the call fails */ - public T sync(final Callable function) throws Exception { + public T sync(@Nonnull final Callable function) throws Exception { return sync(function, Integer.MAX_VALUE); } @@ -174,12 +180,8 @@ public abstract class TaskManager { * @return Method result * @throws Exception If the call fails */ - public T sync(final Callable function, int timeout) throws Exception { - if (PlotSquared.get().isMainThread(Thread.currentThread())) { - return function.call(); - } - return this.callMethodSync(function).get(timeout, TimeUnit.MILLISECONDS); - } + public abstract T sync(@Nonnull final Callable function, final int timeout) + throws Exception; /** * Call a method synchronously and return a future with From 43d058d3db4d4ed6bfe2dac65623a6ede79fd244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 17 Jul 2020 17:39:41 +0200 Subject: [PATCH 4/5] Address comments --- .../bukkit/inject/BukkitModule.java | 2 - .../bukkit/listener/ChunkListener.java | 12 ++--- .../bukkit/listener/PlayerEvents.java | 6 +-- .../com/plotsquared/core/command/Trim.java | 4 +- .../java/com/plotsquared/core/plot/Plot.java | 4 +- .../core/plot/expiration/ExpireManager.java | 2 +- .../plotsquared/core/util/RegionManager.java | 2 +- .../core/util/task/TaskManager.java | 46 ++++++++++++++++++- 8 files changed, 58 insertions(+), 20 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java index e3e18b04b..b558aee4f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java @@ -64,10 +64,8 @@ import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.extension.platform.Actor; -import io.papermc.lib.PaperLib; import lombok.RequiredArgsConstructor; import org.bukkit.Bukkit; import org.bukkit.command.ConsoleCommandSender; diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java index 7f7143758..bf756fcf0 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java @@ -60,6 +60,7 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import java.lang.reflect.Method; import java.util.HashSet; +import java.util.Objects; import static com.plotsquared.core.util.ReflectionUtils.getRefClass; @@ -257,15 +258,13 @@ public class ChunkListener implements Listener { final Integer currentIndex = TaskManager.index.get(); PlotSquaredTask task = TaskManager.runTaskRepeat(() -> { if (!chunk.isLoaded()) { - TaskManager.tasks.get(currentIndex).cancel(); - TaskManager.tasks.remove(currentIndex); + Objects.requireNonNull(TaskManager.removeTask(currentIndex)).cancel(); chunk.unload(true); return; } BlockState[] tiles = chunk.getTileEntities(); if (tiles.length == 0) { - TaskManager.tasks.get(currentIndex).cancel(); - TaskManager.tasks.remove(currentIndex); + Objects.requireNonNull(TaskManager.removeTask(currentIndex)).cancel(); chunk.unload(true); return; } @@ -273,8 +272,7 @@ public class ChunkListener implements Listener { int i = 0; while (System.currentTimeMillis() - start < 250) { if (i >= tiles.length - Settings.Chunk_Processor.MAX_TILES) { - TaskManager.tasks.get(currentIndex).cancel(); - TaskManager.tasks.remove(currentIndex); + Objects.requireNonNull(TaskManager.removeTask(currentIndex)).cancel(); chunk.unload(true); return; } @@ -282,7 +280,7 @@ public class ChunkListener implements Listener { i++; } }, TaskTime.ticks(5L)); - TaskManager.tasks.put(currentIndex, task); + TaskManager.addTask(task, currentIndex); } public boolean processChunk(Chunk chunk, boolean unload) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 61e40742f..d85afbbef 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -842,7 +842,7 @@ import java.util.regex.Pattern; Player player = event.getPlayer(); BukkitPlayer pp = BukkitUtil.getPlayer(player); // Cancel teleport - if (TaskManager.TELEPORT_QUEUE.remove(pp.getName())) { + if (TaskManager.removeFromTeleportQueue(pp.getName())) { MainUtil.sendMessage(pp, Captions.TELEPORT_FAILED); } // Set last location @@ -904,7 +904,7 @@ import java.util.regex.Pattern; Player player = event.getPlayer(); BukkitPlayer pp = BukkitUtil.getPlayer(player); // Cancel teleport - if (TaskManager.TELEPORT_QUEUE.remove(pp.getName())) { + if (TaskManager.removeFromTeleportQueue(pp.getName())) { MainUtil.sendMessage(pp, Captions.TELEPORT_FAILED); } // Set last location @@ -2417,7 +2417,7 @@ import java.util.regex.Pattern; } @EventHandler(priority = EventPriority.MONITOR) public void onLeave(PlayerQuitEvent event) { - TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName()); + TaskManager.removeFromTeleportQueue(event.getPlayer().getName()); BukkitPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); pp.unregister(); this.logout(pp.getUUID()); diff --git a/Core/src/main/java/com/plotsquared/core/command/Trim.java b/Core/src/main/java/com/plotsquared/core/command/Trim.java index 18aa48475..3afe16c56 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Trim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Trim.java @@ -121,7 +121,7 @@ public class Trim extends SubCommand { } } }).thenAccept(ignore -> - TaskManager.getPlatformImplementation().taskLater(result, TaskTime.ticks(1))); + TaskManager.getPlatformImplementation().taskLater(result, TaskTime.ticks(1L))); return true; } @@ -196,7 +196,7 @@ public class Trim extends SubCommand { queue.regenChunk(value.getX(), value.getZ()); } }).thenAccept(ignore -> TaskManager.getPlatformImplementation() - .taskLater(this, TaskTime.ticks(1))); + .taskLater(this, TaskTime.ticks(1L))); } }; } else { diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 6b5d9d723..93084adee 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -2996,9 +2996,9 @@ public class Plot { MainUtil .sendMessage(player, Captions.TELEPORT_IN_SECONDS, Settings.Teleport.DELAY + ""); final String name = player.getName(); - TaskManager.TELEPORT_QUEUE.add(name); + TaskManager.addToTeleportQueue(name); TaskManager.runTaskLater(() -> { - if (!TaskManager.TELEPORT_QUEUE.remove(name)) { + if (!TaskManager.removeFromTeleportQueue(name)) { return; } if (player.isOnline()) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java index 0835ba8b1..68f2c4b89 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java @@ -377,7 +377,7 @@ public class ExpireManager { ExpireManager.this.running = 2; runTask(expiredTask); } - }, TaskTime.ticks(86400000)); + }, TaskTime.ticks(86400000L)); } else { TaskManager.runTaskLaterAsync(task, TaskTime.seconds(10L)); } diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java index 3afb51724..0c7d9fc9f 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java @@ -101,7 +101,7 @@ public abstract class RegionManager { .thenRun(() -> task.run(value)); } }).thenAccept(ignore -> - TaskManager.getPlatformImplementation().taskLater(whenDone, TaskTime.ticks(1))); + TaskManager.getPlatformImplementation().taskLater(whenDone, TaskTime.ticks(1L))); }); } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java index fdc04b620..9a120e297 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java @@ -35,6 +35,8 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; @@ -51,12 +53,52 @@ import java.util.concurrent.atomic.AtomicInteger; */ public abstract class TaskManager { - public static final HashSet TELEPORT_QUEUE = new HashSet<>(); - public static final HashMap tasks = new HashMap<>(); + private static final Set teleportQueue = new HashSet<>(); + private static final Map tasks = new HashMap<>(); + public static AtomicInteger index = new AtomicInteger(0); @Getter @Setter private static TaskManager platformImplementation; + /** + * Add a string to the teleport queue + * + * @param string String to add + */ + public static void addToTeleportQueue(@Nonnull final String string) { + teleportQueue.add(string); + } + + /** + * Remove a string from the teleport queue + * + * @param string String to remove + * return {@code true} if the value was stored in the map, or {@code false} + */ + public static boolean removeFromTeleportQueue(@Nonnull final String string) { + return teleportQueue.remove(string); + } + + /** + * Add a task to the task map + * + * @param task Task + * @param id Task ID + */ + public static void addTask(@Nonnull final PlotSquaredTask task, final int id) { + tasks.put(id, task); + } + + /** + * Remove a task from the task map and return the stored value + * + * @param id Task ID + * @return Task if stored, or {@code null} + */ + @Nullable public static PlotSquaredTask removeTask(final int id) { + return tasks.get(id); + } + /** * Run a repeating synchronous task. If using a platform scheduler, * this is guaranteed to run on the server thread From 932052772c927ceec4588ded080c86375b674fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 17 Jul 2020 17:51:03 +0200 Subject: [PATCH 5/5] Fix edge cases for time conversion --- .../com/plotsquared/bukkit/util/task/PaperTimeConverter.java | 4 ++-- .../com/plotsquared/bukkit/util/task/SpigotTimeConverter.java | 4 ++-- .../main/java/com/plotsquared/core/util/task/TaskManager.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java index 883708f5f..53fd535c2 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/PaperTimeConverter.java @@ -37,11 +37,11 @@ import javax.annotation.Nonnegative; public final class PaperTimeConverter implements TaskTime.TimeConverter { @Override public long msToTicks(@Nonnegative final long ms) { - return (long) (ms / Bukkit.getAverageTickTime()); + return Math.max(1L, (long) (ms / Bukkit.getAverageTickTime())); } @Override public long ticksToMs(@Nonnegative final long ticks) { - return (long) (ticks * Bukkit.getAverageTickTime()); + return Math.max(1L, (long) (ticks * Bukkit.getAverageTickTime())); } } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java index 86c9673d8..1605e7b77 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/SpigotTimeConverter.java @@ -37,11 +37,11 @@ public final class SpigotTimeConverter implements TaskTime.TimeConverter { private static final long MS_PER_TICKS = 50L; @Override public long msToTicks(@Nonnegative final long ms) { - return ms / MS_PER_TICKS; + return Math.max(1L, ms / MS_PER_TICKS); } @Override public long ticksToMs(@Nonnegative final long ticks) { - return ticks * MS_PER_TICKS; + return Math.max(1L, ticks * MS_PER_TICKS); } } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java index 9a120e297..7be015532 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/TaskManager.java @@ -96,7 +96,7 @@ public abstract class TaskManager { * @return Task if stored, or {@code null} */ @Nullable public static PlotSquaredTask removeTask(final int id) { - return tasks.get(id); + return tasks.remove(id); } /**