Merge pull request #2 from ColdeZhang/folia-1.20.1

Folia 1.20.1
This commit is contained in:
张宇衡 2023-08-08 10:22:51 +08:00 committed by GitHub
commit 3d8d9d9019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 210 additions and 128 deletions

12
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>site.deercloud</groupId> <groupId>site.deercloud</groupId>
<artifactId>LiteWorldEdit</artifactId> <artifactId>LiteWorldEdit</artifactId>
<version>2.1.1</version> <version>2.1.3-Folia-1.20.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>LiteWorldEdit</name> <name>LiteWorldEdit</name>
@ -63,13 +63,17 @@
<id>sonatype</id> <id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url> <url>https://oss.sonatype.org/content/groups/public/</url>
</repository> </repository>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>dev.folia</groupId>
<artifactId>spigot-api</artifactId> <artifactId>folia-api</artifactId>
<version>1.17-R0.1-SNAPSHOT</version> <version>1.20.1-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -40,7 +40,7 @@ public class Commands implements TabExecutor {
print_help(sender); print_help(sender);
return true; return true;
} else if (Objects.equals(args[0], "cancel")) { } else if (Objects.equals(args[0], "cancel")) {
cancerJobs(sender); cancelJobs(sender);
return true; return true;
} else if (Objects.equals(args[0], "reload")) { } else if (Objects.equals(args[0], "reload")) {
reloadConfigs(sender); reloadConfigs(sender);
@ -60,11 +60,11 @@ public class Commands implements TabExecutor {
private static void resumeJobs(CommandSender sender) { private static void resumeJobs(CommandSender sender) {
if (sender instanceof Player) { if (sender instanceof Player) {
Player player = (Player) sender; Player player = (Player) sender;
if (LiteWorldEdit.instance.getCache().getQueueOf(player) == null) { if (LiteWorldEdit.instance.getCache().getPlayer(player).hasJob()) {
sender.sendMessage("你没有正在进行的任务。"); LiteWorldEdit.instance.getCache().getPlayer(player).resumeJob();
} else {
LiteWorldEdit.instance.getCache().getQueueOf(player).resume();
sender.sendMessage("已恢复。"); sender.sendMessage("已恢复。");
} else {
sender.sendMessage("你没有正在进行的任务。");
} }
} else { } else {
sender.sendMessage("该命令只能由玩家执行。"); sender.sendMessage("该命令只能由玩家执行。");
@ -74,11 +74,11 @@ public class Commands implements TabExecutor {
private static void pauseJobs(CommandSender sender) { private static void pauseJobs(CommandSender sender) {
if (sender instanceof Player) { if (sender instanceof Player) {
Player player = (Player) sender; Player player = (Player) sender;
if (LiteWorldEdit.instance.getCache().getQueueOf(player) == null) { if (LiteWorldEdit.instance.getCache().getPlayer(player).hasJob()) {
sender.sendMessage("你没有正在进行的任务。"); LiteWorldEdit.instance.getCache().getPlayer(player).pauseJob();
} else {
LiteWorldEdit.instance.getCache().getQueueOf(player).pause();
sender.sendMessage("已暂停。"); sender.sendMessage("已暂停。");
} else {
sender.sendMessage("你没有正在进行的任务。");
} }
} else { } else {
sender.sendMessage("该命令只能由玩家执行。"); 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) { if (sender instanceof Player) {
Player player = (Player) sender; Player player = (Player) sender;
if (LiteWorldEdit.instance.getCache().getQueueOf(player) == null) { if (LiteWorldEdit.instance.getCache().getPlayer(player).hasJob()) {
sender.sendMessage("你没有正在进行的任务。"); LiteWorldEdit.instance.getCache().getPlayer(player).cancelJob();
} else {
LiteWorldEdit.instance.getCache().getQueueOf(player).cancel();
sender.sendMessage("已取消。"); sender.sendMessage("已取消。");
} else {
sender.sendMessage("你没有正在进行的任务。");
} }
} else { } else {
sender.sendMessage("该命令只能由玩家执行。"); sender.sendMessage("该命令只能由玩家执行。");
@ -195,7 +195,7 @@ public class Commands implements TabExecutor {
private static Vector2 getVector2(CommandSender sender, String[] args, Player player) { private static Vector2 getVector2(CommandSender sender, String[] args, Player player) {
Integer indexA = Integer.parseInt(args[1]); Integer indexA = Integer.parseInt(args[1]);
Integer indexB = Integer.parseInt(args[2]); 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) { if (points == null) {
sender.sendMessage("你没有设置任何点。"); sender.sendMessage("你没有设置任何点。");
return null; return null;
@ -229,7 +229,7 @@ public class Commands implements TabExecutor {
return; return;
} }
Player player = (Player) sender; 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) { if (points != null) {
sender.sendMessage("你创建的点:"); sender.sendMessage("你创建的点:");
for (Map.Entry<Integer, Point> entry : points.entrySet()) { for (Map.Entry<Integer, Point> entry : points.entrySet()) {
@ -258,7 +258,7 @@ public class Commands implements TabExecutor {
return true; return true;
} }
Point point = new Point(x, y, z, player); 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请使用已有点序号覆盖已有点。"); sender.sendMessage("点的数量不允许超过20请使用已有点序号覆盖已有点。");
return true; return true;
} }

View File

@ -2,11 +2,17 @@ package site.deercloud.liteworldedit;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
public class Events implements Listener { public class Events implements Listener {
@EventHandler @EventHandler
public void onPlayerQuit(PlayerQuitEvent event) { 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++) { 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); Location location = new Location(world, (double) x, (double) y, (double) z);
Remove remove_job = new Remove(location, player); 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++) { 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); Location location = new Location(world, (double) x, (double) y, (double) z);
Place place_job = new Place(location, player, block); 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) { if (block1.getType() == Material.AIR) {
Location location = new Location(world, (double) x, (double) y, (double) z); Location location = new Location(world, (double) x, (double) y, (double) z);
Place place_job = new Place(location, player, block); Place place_job = new Place(location, player, block);
LiteWorldEdit.instance.getCache().addJob(player, place_job); LiteWorldEdit.instance.getCache().getPlayer(player).addJob(place_job);
break; break;
} }
} }

View File

@ -1,15 +1,24 @@
package site.deercloud.liteworldedit; package site.deercloud.liteworldedit;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitScheduler;
import site.deercloud.liteworldedit.Jobs.Job; import site.deercloud.liteworldedit.Jobs.Job;
import site.deercloud.liteworldedit.Jobs.JobErrCode; import site.deercloud.liteworldedit.Jobs.JobErrCode;
import site.deercloud.liteworldedit.Managers.ConfigManager; import site.deercloud.liteworldedit.Managers.ConfigManager;
import site.deercloud.liteworldedit.Managers.Cache; 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.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import static site.deercloud.liteworldedit.SchedulerUtil.runAtFixedRateEntity;
public final class LiteWorldEdit extends JavaPlugin { public final class LiteWorldEdit extends JavaPlugin {
@ -20,37 +29,6 @@ public final class LiteWorldEdit extends JavaPlugin {
_config = new ConfigManager(); _config = new ConfigManager();
_cache = new Cache(); _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); Bukkit.getPluginManager().registerEvents(new Events(), this);
Objects.requireNonNull(Bukkit.getPluginCommand("LiteWorldEdit")).setExecutor(new Commands()); Objects.requireNonNull(Bukkit.getPluginCommand("LiteWorldEdit")).setExecutor(new Commands());
Objects.requireNonNull(Bukkit.getPluginCommand("LiteWorldEdit")).setTabCompleter(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 org.bukkit.entity.Player;
import site.deercloud.liteworldedit.Jobs.Job; import site.deercloud.liteworldedit.Jobs.Job;
import site.deercloud.liteworldedit.XPlayer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class Cache { public class Cache {
private final Map<String, Map<Integer, Point>> _points;
private final Map<String, JobQueue> _jobs; private final Map<String, XPlayer> players;
private String _last_jobs_player; // 上一次被获取任务的玩家uuid
public Cache() { public Cache() {
_points = new HashMap<String, Map<Integer, Point>>(); this.players = new HashMap<>();
_jobs = new HashMap<String, JobQueue>();
} }
public boolean addPoint(Player player, Integer index, Point point) { public void playerJoin(Player player) {
if (!_points.containsKey(player.getUniqueId().toString())) { players.put(player.getName(), new XPlayer(player));
_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 addJob(Player player, Job job) { public void playerQuit(Player player) {
if (!_jobs.containsKey(player.getUniqueId().toString())) { players.remove(player.getName());
_jobs.put(player.getUniqueId().toString(), new JobQueue(player));
}
_jobs.get(player.getUniqueId().toString()).add(job);
} }
public Job getOneJob() { public XPlayer getPlayer(Player player) {
String player = getNextPlayer(); String name = player.getName();
if (player == null) { if (!players.containsKey(name)) playerJoin(player);
return null; return players.get(name);
}
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;
} }
} }

View File

@ -26,6 +26,7 @@ public class JobQueue {
public JobQueue(Player player) { public JobQueue(Player player) {
this.player = player; this.player = player;
this.bar.addPlayer(player); this.bar.addPlayer(player);
this.bar.setVisible(false);
} }
public void add(Job job) { 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 ] authors: [ Luming ]
description: 生存用简易创世神。 description: 生存用简易创世神。
website: https://blog.deercloud.site website: https://blog.deercloud.site
folia-supported: true
commands: commands:
LiteWorldEdit: LiteWorldEdit:
description: 简易创世神命令 description: 简易创世神命令