diff --git a/pom.xml b/pom.xml index 9c3367c..0504ccb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ site.deercloud LiteWorldEdit - 2.1.1-Folia-1.20.1 + 2.1.3-Folia-1.20.1 jar LiteWorldEdit diff --git a/src/main/java/site/deercloud/liteworldedit/Commands.java b/src/main/java/site/deercloud/liteworldedit/Commands.java index e297005..fb0d801 100644 --- a/src/main/java/site/deercloud/liteworldedit/Commands.java +++ b/src/main/java/site/deercloud/liteworldedit/Commands.java @@ -40,7 +40,7 @@ public class Commands implements TabExecutor { print_help(sender); return true; } else if (Objects.equals(args[0], "cancel")) { - cancerJobs(sender); + cancelJobs(sender); return true; } else if (Objects.equals(args[0], "reload")) { reloadConfigs(sender); @@ -60,11 +60,11 @@ public class Commands implements TabExecutor { private static void resumeJobs(CommandSender sender) { if (sender instanceof Player) { Player player = (Player) sender; - if (LiteWorldEdit.instance.getCache().getQueueOf(player) == null) { - sender.sendMessage("你没有正在进行的任务。"); - } else { - LiteWorldEdit.instance.getCache().getQueueOf(player).resume(); + if (LiteWorldEdit.instance.getCache().getPlayer(player).hasJob()) { + LiteWorldEdit.instance.getCache().getPlayer(player).resumeJob(); sender.sendMessage("已恢复。"); + } else { + sender.sendMessage("你没有正在进行的任务。"); } } else { sender.sendMessage("该命令只能由玩家执行。"); @@ -74,11 +74,11 @@ public class Commands implements TabExecutor { private static void pauseJobs(CommandSender sender) { if (sender instanceof Player) { Player player = (Player) sender; - if (LiteWorldEdit.instance.getCache().getQueueOf(player) == null) { - sender.sendMessage("你没有正在进行的任务。"); - } else { - LiteWorldEdit.instance.getCache().getQueueOf(player).pause(); + if (LiteWorldEdit.instance.getCache().getPlayer(player).hasJob()) { + LiteWorldEdit.instance.getCache().getPlayer(player).pauseJob(); sender.sendMessage("已暂停。"); + } else { + sender.sendMessage("你没有正在进行的任务。"); } } else { sender.sendMessage("该命令只能由玩家执行。"); @@ -100,14 +100,14 @@ public class Commands implements TabExecutor { } } - private static void cancerJobs(CommandSender sender) { + private static void cancelJobs(CommandSender sender) { if (sender instanceof Player) { Player player = (Player) sender; - if (LiteWorldEdit.instance.getCache().getQueueOf(player) == null) { - sender.sendMessage("你没有正在进行的任务。"); - } else { - LiteWorldEdit.instance.getCache().getQueueOf(player).cancel(); + if (LiteWorldEdit.instance.getCache().getPlayer(player).hasJob()) { + LiteWorldEdit.instance.getCache().getPlayer(player).cancelJob(); sender.sendMessage("已取消。"); + } else { + sender.sendMessage("你没有正在进行的任务。"); } } else { sender.sendMessage("该命令只能由玩家执行。"); @@ -195,7 +195,7 @@ public class Commands implements TabExecutor { private static Vector2 getVector2(CommandSender sender, String[] args, Player player) { Integer indexA = Integer.parseInt(args[1]); Integer indexB = Integer.parseInt(args[2]); - Map points = LiteWorldEdit.instance.getCache().getPoints(player); + Map points = LiteWorldEdit.instance.getCache().getPlayer(player).getPoints(); if (points == null) { sender.sendMessage("你没有设置任何点。"); return null; @@ -229,7 +229,7 @@ public class Commands implements TabExecutor { return; } Player player = (Player) sender; - Map points = LiteWorldEdit.instance.getCache().getPoints(player); + Map points = LiteWorldEdit.instance.getCache().getPlayer(player).getPoints(); if (points != null) { sender.sendMessage("你创建的点:"); for (Map.Entry entry : points.entrySet()) { @@ -258,7 +258,7 @@ public class Commands implements TabExecutor { return true; } Point point = new Point(x, y, z, player); - if (!LiteWorldEdit.instance.getCache().addPoint(player, index, point)) { + if (!LiteWorldEdit.instance.getCache().getPlayer(player).addPoint(index, point)) { sender.sendMessage("点的数量不允许超过20,请使用已有点序号覆盖已有点。"); return true; } diff --git a/src/main/java/site/deercloud/liteworldedit/Events.java b/src/main/java/site/deercloud/liteworldedit/Events.java index d0ead6d..465319c 100644 --- a/src/main/java/site/deercloud/liteworldedit/Events.java +++ b/src/main/java/site/deercloud/liteworldedit/Events.java @@ -2,11 +2,17 @@ package site.deercloud.liteworldedit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; public class Events implements Listener { @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { - LiteWorldEdit.instance.getCache().deletePlayerCache(event.getPlayer()); + LiteWorldEdit.instance.getCache().playerQuit(event.getPlayer()); + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + LiteWorldEdit.instance.getCache().playerJoin(event.getPlayer()); } } diff --git a/src/main/java/site/deercloud/liteworldedit/JobGenerator/Empty.java b/src/main/java/site/deercloud/liteworldedit/JobGenerator/Empty.java index d4ed860..a892602 100644 --- a/src/main/java/site/deercloud/liteworldedit/JobGenerator/Empty.java +++ b/src/main/java/site/deercloud/liteworldedit/JobGenerator/Empty.java @@ -14,7 +14,7 @@ public class Empty { for (int z = Math.min(p1.z, p2.z); z <= Math.max(p1.z, p2.z); z++) { Location location = new Location(world, (double) x, (double) y, (double) z); Remove remove_job = new Remove(location, player); - LiteWorldEdit.instance.getCache().addJob(player, remove_job); + LiteWorldEdit.instance.getCache().getPlayer(player).addJob(remove_job); } } } diff --git a/src/main/java/site/deercloud/liteworldedit/JobGenerator/Fill.java b/src/main/java/site/deercloud/liteworldedit/JobGenerator/Fill.java index ceeb1fe..1923e56 100644 --- a/src/main/java/site/deercloud/liteworldedit/JobGenerator/Fill.java +++ b/src/main/java/site/deercloud/liteworldedit/JobGenerator/Fill.java @@ -17,7 +17,7 @@ public class Fill { for (int z = Math.min(p1.z, p2.z); z <= Math.max(p1.z, p2.z); z++) { Location location = new Location(world, (double) x, (double) y, (double) z); Place place_job = new Place(location, player, block); - LiteWorldEdit.instance.getCache().addJob(player, place_job); + LiteWorldEdit.instance.getCache().getPlayer(player).addJob(place_job); } } } diff --git a/src/main/java/site/deercloud/liteworldedit/JobGenerator/OverLay.java b/src/main/java/site/deercloud/liteworldedit/JobGenerator/OverLay.java index ba9cbc6..acd66f6 100644 --- a/src/main/java/site/deercloud/liteworldedit/JobGenerator/OverLay.java +++ b/src/main/java/site/deercloud/liteworldedit/JobGenerator/OverLay.java @@ -19,7 +19,7 @@ public class OverLay { if (block1.getType() == Material.AIR) { Location location = new Location(world, (double) x, (double) y, (double) z); Place place_job = new Place(location, player, block); - LiteWorldEdit.instance.getCache().addJob(player, place_job); + LiteWorldEdit.instance.getCache().getPlayer(player).addJob(place_job); break; } } diff --git a/src/main/java/site/deercloud/liteworldedit/LiteWorldEdit.java b/src/main/java/site/deercloud/liteworldedit/LiteWorldEdit.java index acaba3a..a8ab20f 100644 --- a/src/main/java/site/deercloud/liteworldedit/LiteWorldEdit.java +++ b/src/main/java/site/deercloud/liteworldedit/LiteWorldEdit.java @@ -1,15 +1,24 @@ package site.deercloud.liteworldedit; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitScheduler; import site.deercloud.liteworldedit.Jobs.Job; import site.deercloud.liteworldedit.Jobs.JobErrCode; import site.deercloud.liteworldedit.Managers.ConfigManager; import site.deercloud.liteworldedit.Managers.Cache; +import site.deercloud.liteworldedit.Task; +import io.papermc.paper.threadedregions.scheduler.AsyncScheduler; import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import static site.deercloud.liteworldedit.SchedulerUtil.runAtFixedRateEntity; public final class LiteWorldEdit extends JavaPlugin { @@ -20,37 +29,6 @@ public final class LiteWorldEdit extends JavaPlugin { _config = new ConfigManager(); _cache = new Cache(); - new BukkitRunnable() { - @Override - public void run() { - Job job = _cache.getOneJob(); - if (job == null) { - return; - } - // 如果任务不可执行 允许在一个tick内多次执行直到任务可执行 - int max_retries = 100; - JobErrCode re; - while ((re = job.Do()) != JobErrCode.OK) { - max_retries--; - if (max_retries <= 0) { - break; - } - if (re.canContinue()) { - job.get_creator().sendTitle("§e警告", "§e" + re.getMessage(), 10, 70, 20); - job = _cache.getOneJob(); - if (job == null) { - return; - } - } else { - Player player = job.get_creator(); - player.sendTitle("§c错误 任务已自动暂停", "§c" + re.getMessage(), 10, 70, 20); - _cache.getQueueOf(player).pause(); - return; - } - } - } - }.runTaskTimer(this, 0, 1); - Bukkit.getPluginManager().registerEvents(new Events(), this); Objects.requireNonNull(Bukkit.getPluginCommand("LiteWorldEdit")).setExecutor(new Commands()); Objects.requireNonNull(Bukkit.getPluginCommand("LiteWorldEdit")).setTabCompleter(new Commands()); diff --git a/src/main/java/site/deercloud/liteworldedit/Managers/Cache.java b/src/main/java/site/deercloud/liteworldedit/Managers/Cache.java index 452117c..9022ce5 100644 --- a/src/main/java/site/deercloud/liteworldedit/Managers/Cache.java +++ b/src/main/java/site/deercloud/liteworldedit/Managers/Cache.java @@ -2,90 +2,30 @@ package site.deercloud.liteworldedit.Managers; import org.bukkit.entity.Player; import site.deercloud.liteworldedit.Jobs.Job; +import site.deercloud.liteworldedit.XPlayer; import java.util.HashMap; import java.util.Map; public class Cache { - private final Map> _points; - private final Map _jobs; - private String _last_jobs_player; // 上一次被获取任务的玩家uuid + + private final Map players; public Cache() { - _points = new HashMap>(); - _jobs = new HashMap(); + this.players = new HashMap<>(); } - public boolean addPoint(Player player, Integer index, Point point) { - if (!_points.containsKey(player.getUniqueId().toString())) { - _points.put(player.getUniqueId().toString(), new HashMap()); - } - if (_points.get(player.getUniqueId().toString()).size() >= 20) { - return false; - } - _points.get(player.getUniqueId().toString()).put(index, point); - return true; + public void playerJoin(Player player) { + players.put(player.getName(), new XPlayer(player)); } - public void addJob(Player player, Job job) { - if (!_jobs.containsKey(player.getUniqueId().toString())) { - _jobs.put(player.getUniqueId().toString(), new JobQueue(player)); - } - _jobs.get(player.getUniqueId().toString()).add(job); + public void playerQuit(Player player) { + players.remove(player.getName()); } - public Job getOneJob() { - String player = getNextPlayer(); - if (player == null) { - return null; - } - if (!_jobs.containsKey(player)) { - return null; - } - return _jobs.get(player).pop(); - } - - public Map getPoints(Player player) { - return _points.get(player.getUniqueId().toString()); - } - - public JobQueue getQueueOf(Player player) { - if (!_jobs.containsKey(player.getUniqueId().toString())) { - return null; - } - if (_jobs.get(player.getUniqueId().toString()).isEmpty()) { - return null; - } - return _jobs.get(player.getUniqueId().toString()); - } - - public void deletePlayerCache(Player player) { - _jobs.remove(player.getUniqueId().toString()); - } - - private String getNextPlayer() { - if (_jobs.size() == 0) { - return null; - } - if (_last_jobs_player == null) { - _last_jobs_player = _jobs.keySet().iterator().next(); - return _last_jobs_player; - } - boolean found = false; - for (String key : _jobs.keySet()) { - if (found) { - // 忽略没有任务的玩家 - if (_jobs.get(key).size() == 0) { - continue; - } - _last_jobs_player = key; - return key; - } - if (key.equals(_last_jobs_player)) { - found = true; - } - } - _last_jobs_player = _jobs.keySet().iterator().next(); - return _last_jobs_player; + public XPlayer getPlayer(Player player) { + String name = player.getName(); + if (!players.containsKey(name)) playerJoin(player); + return players.get(name); } } diff --git a/src/main/java/site/deercloud/liteworldedit/Managers/JobQueue.java b/src/main/java/site/deercloud/liteworldedit/Managers/JobQueue.java index 9b4125e..8ed072c 100644 --- a/src/main/java/site/deercloud/liteworldedit/Managers/JobQueue.java +++ b/src/main/java/site/deercloud/liteworldedit/Managers/JobQueue.java @@ -26,6 +26,7 @@ public class JobQueue { public JobQueue(Player player) { this.player = player; this.bar.addPlayer(player); + bar.setVisible(false); } public void add(Job job) { diff --git a/src/main/java/site/deercloud/liteworldedit/SchedulerUtil.java b/src/main/java/site/deercloud/liteworldedit/SchedulerUtil.java new file mode 100644 index 0000000..ccdd4c7 --- /dev/null +++ b/src/main/java/site/deercloud/liteworldedit/SchedulerUtil.java @@ -0,0 +1,35 @@ +package site.deercloud.liteworldedit; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; + +public class SchedulerUtil { + + private static Boolean IS_FOLIA = null; + + private static boolean tryFolia() { + try { + Bukkit.getAsyncScheduler(); + return true; + } catch (Throwable ignored) { + } + return false; + } + + public static Boolean isFolia() { + if (IS_FOLIA == null) IS_FOLIA = tryFolia(); + return IS_FOLIA; + } + + public static void runLaterEntity(Entity entity, Plugin plugin, Runnable runnable, int ticks) { + if (isFolia()) entity.getScheduler().runDelayed(plugin, (task) -> runnable.run(), null, ticks); + else Bukkit.getScheduler().runTaskLater(plugin, runnable, ticks); + } + + public static void runAtFixedRateEntity(Entity entity, Plugin plugin, Runnable runnable, int ticks) { + if (isFolia()) entity.getScheduler().runAtFixedRate(plugin, (task) -> runnable.run(), null, ticks, ticks); + else Bukkit.getScheduler().runTaskTimer(plugin, runnable, ticks, ticks); + } +} diff --git a/src/main/java/site/deercloud/liteworldedit/Task.java b/src/main/java/site/deercloud/liteworldedit/Task.java new file mode 100644 index 0000000..4994ae8 --- /dev/null +++ b/src/main/java/site/deercloud/liteworldedit/Task.java @@ -0,0 +1,54 @@ +package site.deercloud.liteworldedit; + +import org.bukkit.entity.Player; +import site.deercloud.liteworldedit.Jobs.Job; +import site.deercloud.liteworldedit.Jobs.JobErrCode; + +public class Task implements Runnable{ + /** + * When an object implementing interface {@code Runnable} is used + * to create a thread, starting the thread causes the object's + * {@code run} method to be called in that separately executing + * thread. + *

+ * The general contract of the method {@code run} is that it may + * take any action whatsoever. + * + * @see Thread#run() + */ + + private final XPlayer xPlayer; + + Task(XPlayer player) { + this.xPlayer = player; + } + + @Override + public void run() { + Job job = this.xPlayer.popJob(); + if (job == null) { + return; + } + // 如果任务不可执行 允许在一个tick内多次执行直到任务可执行 + int max_retries = 100; + JobErrCode re; + while ((re = job.Do()) != JobErrCode.OK) { + max_retries--; + if (max_retries <= 0) { + break; + } + if (re.canContinue()) { + job.get_creator().sendTitle("§e警告", "§e" + re.getMessage(), 10, 70, 20); + job = this.xPlayer.popJob(); + if (job == null) { + return; + } + } else { + Player player = job.get_creator(); + player.sendTitle("§c错误 任务已自动暂停", "§c" + re.getMessage(), 10, 70, 20); + this.xPlayer.pauseJob(); + return; + } + } + } +} diff --git a/src/main/java/site/deercloud/liteworldedit/XPlayer.java b/src/main/java/site/deercloud/liteworldedit/XPlayer.java new file mode 100644 index 0000000..662f16b --- /dev/null +++ b/src/main/java/site/deercloud/liteworldedit/XPlayer.java @@ -0,0 +1,63 @@ +package site.deercloud.liteworldedit; + +import org.bukkit.entity.Player; +import site.deercloud.liteworldedit.Jobs.Job; +import site.deercloud.liteworldedit.Managers.JobQueue; +import site.deercloud.liteworldedit.Managers.Point; + +import java.util.HashMap; +import java.util.Map; + +import static site.deercloud.liteworldedit.SchedulerUtil.runAtFixedRateEntity; + +public class XPlayer { + + private final Map points; + private final Player player; + private final JobQueue queue; + private final Task task; + + public XPlayer(Player player) { + this.player = player; + this.points = new HashMap<>(); + this.queue = new JobQueue(player); + this.task = new Task(this); + runAtFixedRateEntity(player, LiteWorldEdit.instance, task, 1); + } + + public void addJob(Job job) { + queue.add(job); + } + + public Job popJob() { + return queue.pop(); + } + + public void pauseJob() { + queue.pause(); + } + + public void resumeJob() { + queue.resume(); + } + + public void cancelJob() { + queue.cancel(); + } + + public boolean hasJob() { + return !queue.isEmpty(); + } + + public boolean addPoint(Integer index, Point point) { + if (points.size() >= 20) { + return false; + } + points.put(index, point); + return true; + } + + public Map getPoints() { + return points; + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index ccb4c28..1a1e146 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -7,6 +7,7 @@ load: STARTUP authors: [ Luming ] description: 生存用简易创世神。 website: https://blog.deercloud.site +folia-supported: true commands: LiteWorldEdit: description: 简易创世神命令