diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java index 60a49bc27..6b8f14ce3 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; @@ -104,6 +106,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; @@ -216,9 +219,16 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl @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.setPlatformImplementation(new BukkitTaskManager(this, timeConverter)); final PlotSquared plotSquared = new PlotSquared(this, "Bukkit"); @@ -380,7 +390,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl this.setGenerator(world); } } - }, 1); + }, TaskTime.ticks(1L)); } // Services are accessed in order @@ -513,7 +523,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl this.startMetrics(); if (Settings.Enabled_Components.WORLDS) { - TaskManager.getImplementation().taskRepeat(this::unload, 20); + TaskManager.getPlatformImplementation().taskRepeat(this::unload, TaskTime.seconds(1L)); try { singleWorldListener = getInjector().getInstance(SingleWorldListener.class); } catch (Exception e) { @@ -978,7 +988,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl } 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 b7eda2e6b..8f644dc25 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; 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..bf756fcf0 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,12 +54,13 @@ 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; +import java.util.Objects; import static com.plotsquared.core.util.ReflectionUtils.getRefClass; @@ -132,7 +134,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,17 +256,15 @@ 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.remove(currentIndex); + Objects.requireNonNull(TaskManager.removeTask(currentIndex)).cancel(); chunk.unload(true); return; } BlockState[] tiles = chunk.getTileEntities(); if (tiles.length == 0) { - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); - TaskManager.tasks.remove(currentIndex); + Objects.requireNonNull(TaskManager.removeTask(currentIndex)).cancel(); chunk.unload(true); return; } @@ -272,16 +272,15 @@ 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.remove(currentIndex); + Objects.requireNonNull(TaskManager.removeTask(currentIndex)).cancel(); chunk.unload(true); return; } tiles[i].getBlock().setType(Material.AIR, false); i++; } - }, 5); - TaskManager.tasks.put(currentIndex, task); + }, TaskTime.ticks(5L)); + 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 ce868a61e..d85afbbef 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() @@ -841,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 @@ -903,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 @@ -2416,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/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java index e95f469af..6b6491a9d 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; @@ -402,9 +403,9 @@ public class BukkitRegionManager extends RegionManager { }); } if (!chunks.isEmpty()) { - TaskManager.runTaskLater(this, 1); + TaskManager.runTaskLater(this, TaskTime.ticks(1L)); } else { - TaskManager.runTaskLater(whenDone, 1); + TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); } } }); @@ -458,7 +459,7 @@ public class BukkitRegionManager extends RegionManager { 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/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index f25fdc621..75ac9a1be 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.getPlatformImplementation().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/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..643c4d8f3 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/BukkitTaskManager.java @@ -0,0 +1,111 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.PlotSquared; +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; +import java.util.concurrent.TimeUnit; + +/** + * 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 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); + } + + @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..53fd535c2 --- /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 Math.max(1L, (long) (ms / Bukkit.getAverageTickTime())); + } + + @Override public long ticksToMs(@Nonnegative final long ticks) { + 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 new file mode 100644 index 000000000..1605e7b77 --- /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 Math.max(1L, ms / MS_PER_TICKS); + } + + @Override public long ticksToMs(@Nonnegative final long ticks) { + return Math.max(1L, ticks * MS_PER_TICKS); + } + +} 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..2c2f051e9 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.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 7b51ea6cf..bb3ae02c3 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.getPlatformImplementation().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/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/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 346eb17ab..4e2ec2a08 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(1L))); return true; } @@ -189,11 +191,12 @@ public class Trim extends SubCommand { } } final QueueCoordinator 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(1L))); } }; } else { 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 46ba52cf7..016a547ea 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; @@ -54,6 +53,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 +366,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)); } }); } @@ -478,21 +478,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.getPlatformImplementation().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) { @@ -511,7 +510,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 3fa208228..f661f6a29 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; @@ -1950,7 +1951,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; } @@ -2913,7 +2914,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) { @@ -3001,16 +3002,16 @@ 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()) { 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())) { @@ -3160,7 +3161,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); @@ -3169,7 +3170,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); @@ -3279,14 +3280,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..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 @@ -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.getPlatformImplementation() + .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.getPlatformImplementation().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.getPlatformImplementation().taskLaterAsync(task, TaskTime.ticks(1L))); } else { doAnalysis.run(); } @@ -376,9 +377,9 @@ public class ExpireManager { ExpireManager.this.running = 2; runTask(expiredTask); } - }, 86400000); + }, TaskTime.ticks(86400000L)); } else { - TaskManager.runTaskLaterAsync(task, 20 * 10); + TaskManager.runTaskLaterAsync(task, TaskTime.seconds(10L)); } } }); 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..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 @@ -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.getPlatformImplementation().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/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/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index db80e90b1..eb40df5b0 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -26,8 +26,13 @@ package com.plotsquared.core.queue; import com.plotsquared.core.PlotSquared; +<<<<<<< HEAD import lombok.Getter; import lombok.Setter; +======= +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.List; 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 7012b8fa6..dce0f43ed 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.QueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator; 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; @@ -174,7 +175,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/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java index dd8a99c8d..bcf5fb58d 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.QueueCoordinator; 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,11 +95,12 @@ 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(1L))); }); } 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 07cc0c618..59da4a707 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.QueueCoordinator; 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; @@ -662,7 +663,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/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/ObjectTaskRunnable.java b/Core/src/main/java/com/plotsquared/core/util/task/ObjectTaskRunnable.java index 63c0ebc8c..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,9 +47,9 @@ public class ObjectTaskRunnable implements Runnable { task.run(); } if (!hasNext) { - TaskManager.runTaskLater(whenDone, 1); + completionFuture.complete(null); } 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..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 @@ -25,144 +25,269 @@ */ package com.plotsquared.core.util.task; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.util.RuntimeExceptionRunnableVal; import lombok.Getter; import lombok.Setter; +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.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; 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<>(); - 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 implementation; + @Getter @Setter private static TaskManager platformImplementation; - public static int runTaskRepeat(Runnable runnable, int interval) { - if (runnable != null) { - if (getImplementation() == null) { - throw new IllegalArgumentException("disabled"); - } - return getImplementation().taskRepeat(runnable, interval); - } - return -1; + /** + * Add a string to the teleport queue + * + * @param string String to add + */ + public static void addToTeleportQueue(@Nonnull final String string) { + teleportQueue.add(string); } - public static int runTaskRepeatAsync(Runnable runnable, int interval) { - if (runnable != null) { - if (getImplementation() == null) { - throw new IllegalArgumentException("disabled"); - } - return getImplementation().taskRepeatAsync(runnable, interval); - } - return -1; + /** + * 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); } - public static void runTaskAsync(Runnable runnable) { + /** + * 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.remove(id); + } + + /** + * 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) { + if (getPlatformImplementation() == null) { + throw new IllegalArgumentException("disabled"); + } + return getPlatformImplementation().taskRepeat(runnable, taskTime); + } + return PlotSquaredTask.nullTask(); + } + + /** + * 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 (getPlatformImplementation() == null) { runnable.run(); return; } - getImplementation().taskAsync(runnable); - } - } - - public static void runTask(Runnable runnable) { - if (runnable != null) { - if (getImplementation() == null) { - runnable.run(); - return; - } - getImplementation().task(runnable); + getPlatformImplementation().taskAsync(runnable); } } /** - * Run task later. + * Run a synchronous task. 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 */ - public static void runTaskLater(Runnable runnable, int delay) { + public static void runTask(@Nullable final Runnable runnable) { if (runnable != null) { - if (getImplementation() == null) { + if (getPlatformImplementation() == null) { runnable.run(); return; } - getImplementation().taskLater(runnable, delay); - } - } - - public static void runTaskLaterAsync(Runnable runnable, int delay) { - if (runnable != null) { - if (getImplementation() == null) { - runnable.run(); - return; - } - getImplementation().taskLaterAsync(runnable, delay); + getPlatformImplementation().task(runnable); } } /** - * Break up a series of tasks so that they can run without lagging the server. + * Run a synchronous task after a given delay. + * If using a platform scheduler, this is guaranteed to run on the server thread * - * @param objects - * @param task - * @param whenDone + * @param runnable Task to run + * @param taskTime Task delay */ - public static void objectTask(Collection objects, final RunnableVal task, - final Runnable whenDone) { + public static void runTaskLater(@Nullable final Runnable runnable, + @Nonnull final TaskTime taskTime) { + if (runnable != null) { + if (getPlatformImplementation() == null) { + runnable.run(); + return; + } + getPlatformImplementation().taskLater(runnable, taskTime); + } + } + + /** + * 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 (getPlatformImplementation() == null) { + runnable.run(); + return; + } + getPlatformImplementation().taskLaterAsync(runnable, taskTime); + } + } + + /** + * 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 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(); } - 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(@Nonnull final Callable function) throws Exception { return sync(function, Integer.MAX_VALUE); } - public T sync(final RunnableVal function, int timeout) { - if (PlotSquared.get().isMainThread(Thread.currentThread())) { - function.run(); - return function.value; - } - 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; - } + /** + * 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 abstract T sync(@Nonnull final Callable function, final int timeout) + throws Exception; - public abstract int taskRepeat(Runnable runnable, int interval); + /** + * 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); - public abstract int taskRepeatAsync(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 void taskAsync(Runnable runnable); + /** + * 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 task(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 taskLater(Runnable runnable, int delay); + /** + * 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 taskLaterAsync(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); + + /** + * 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()); + } + } + + } + +}