folia兼容 - 测试可用

This commit is contained in:
张宇衡 2023-07-01 18:39:30 +08:00
parent 07ef4aaf6a
commit 99539a7369
13 changed files with 203 additions and 125 deletions

View File

@ -6,7 +6,7 @@
<groupId>site.deercloud</groupId>
<artifactId>LiteWorldEdit</artifactId>
<version>2.1.1-Folia-1.20.1</version>
<version>2.1.3-Folia-1.20.1</version>
<packaging>jar</packaging>
<name>LiteWorldEdit</name>

View File

@ -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<Integer, Point> points = LiteWorldEdit.instance.getCache().getPoints(player);
Map<Integer, Point> 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<Integer, Point> points = LiteWorldEdit.instance.getCache().getPoints(player);
Map<Integer, Point> points = LiteWorldEdit.instance.getCache().getPlayer(player).getPoints();
if (points != null) {
sender.sendMessage("你创建的点:");
for (Map.Entry<Integer, Point> 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;
}

View File

@ -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());
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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<String, Map<Integer, Point>> _points;
private final Map<String, JobQueue> _jobs;
private String _last_jobs_player; // 上一次被获取任务的玩家uuid
private final Map<String, XPlayer> players;
public Cache() {
_points = new HashMap<String, Map<Integer, Point>>();
_jobs = new HashMap<String, JobQueue>();
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<Integer, Point>());
}
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<Integer, Point> 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);
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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.
* <p>
* 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;
}
}
}
}

View File

@ -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<Integer, Point> 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<Integer, Point> getPoints() {
return points;
}
}

View File

@ -7,6 +7,7 @@ load: STARTUP
authors: [ Luming ]
description: 生存用简易创世神。
website: https://blog.deercloud.site
folia-supported: true
commands:
LiteWorldEdit:
description: 简易创世神命令