diff --git a/pom.xml b/pom.xml
index 2474129..79f116e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
- 8
+ 21
cc.carm.plugin.userprefix
${project.jdk.version}
@@ -76,6 +76,11 @@
https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+ papermc
+ https://repo.papermc.io/repository/maven-public/
+
+
luck-repo
https://repo.lucko.me/
@@ -185,10 +190,17 @@
provided
+
+
+
+
+
+
+
- org.spigotmc
- spigot-api
- 1.17-R0.1-SNAPSHOT
+ dev.folia
+ folia-api
+ 1.21.4-R0.1-SNAPSHOT
provided
diff --git a/src/main/java/cc/carm/plugin/userprefix/Main.java b/src/main/java/cc/carm/plugin/userprefix/Main.java
index 0a8aec7..33f7800 100644
--- a/src/main/java/cc/carm/plugin/userprefix/Main.java
+++ b/src/main/java/cc/carm/plugin/userprefix/Main.java
@@ -8,6 +8,7 @@ import cc.carm.lib.easyplugin.utils.MessageUtils;
import cc.carm.plugin.userprefix.command.AdminCommand;
import cc.carm.plugin.userprefix.command.UserCommand;
import cc.carm.plugin.userprefix.conf.PluginConfig;
+import cc.carm.plugin.userprefix.folia.FoliaScheduler;
import cc.carm.plugin.userprefix.hooker.UserPrefixExpansion;
import cc.carm.plugin.userprefix.listener.ChatListener;
import cc.carm.plugin.userprefix.listener.UserListener;
@@ -28,6 +29,9 @@ public class Main extends EasyPlugin {
private static Main instance;
+ protected FoliaScheduler foliaScheduler;
+ protected boolean onFolia;
+
protected ConfigManager configManager;
protected PrefixManager prefixManager;
protected UserManager userManager;
@@ -36,6 +40,14 @@ public class Main extends EasyPlugin {
protected boolean initialize() {
instance = this;
+ try {
+ Class.forName("io.papermc.paper.threadedregions.RegionizedServerInitEvent");
+ this.onFolia = true;
+ } catch (ClassNotFoundException e) {
+ this.onFolia = false;
+ }
+ this.foliaScheduler = new FoliaScheduler(this, this.onFolia);
+
log("加载插件配置...");
this.configManager = new ConfigManager(getDataFolder());
this.prefixManager = new PrefixManager();
@@ -87,11 +99,14 @@ public class Main extends EasyPlugin {
if (PluginConfig.CHECK_UPDATE.getNotNull()) {
log("开始检查更新...");
- getScheduler().runAsync(GHUpdateChecker.runner(this));
+ this.foliaScheduler.runAsync(GHUpdateChecker.runner(this));
} else {
log("已禁用检查更新,跳过。");
}
+ if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull() && this.isOnFolia()) {
+ log("插件正运行在 Folia 服务端上,头顶前缀功能不可用");
+ }
Bukkit.getOnlinePlayers().forEach(userManager::initPlayer); // 适配热重载
log("&7感谢您使用 &3&lUserPrefix " + getDescription().getVersion() + "&7!");
@@ -113,6 +128,14 @@ public class Main extends EasyPlugin {
log("&7本插件由 &b&lYourCraft &7提供长期支持与维护。");
}
+ public boolean isOnFolia() {
+ return this.onFolia;
+ }
+
+ public FoliaScheduler getFoliaScheduler() {
+ return this.foliaScheduler;
+ }
+
@Override
public boolean isDebugging() {
return PluginConfig.DEBUG.getNotNull();
diff --git a/src/main/java/cc/carm/plugin/userprefix/conf/PluginConfig.java b/src/main/java/cc/carm/plugin/userprefix/conf/PluginConfig.java
index 7dd53be..0cf2457 100644
--- a/src/main/java/cc/carm/plugin/userprefix/conf/PluginConfig.java
+++ b/src/main/java/cc/carm/plugin/userprefix/conf/PluginConfig.java
@@ -163,7 +163,7 @@ public class PluginConfig implements Configuration {
@HeaderComments({"当选择了默认前缀时显示的物品"})
public static final ConfiguredItem USING = ConfiguredItem.create()
.defaultType(Material.NAME_TAG)
- .defaultEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1)
+ .defaultEnchant(Enchantment.PROTECTION, 1)
.defaultFlags(ItemFlag.HIDE_ENCHANTS)
.defaultName("&f默认玩家前缀")
.defaultLore("", "&a✔ 您正在使用该前缀")
diff --git a/src/main/java/cc/carm/plugin/userprefix/conf/prefix/PrefixConfig.java b/src/main/java/cc/carm/plugin/userprefix/conf/prefix/PrefixConfig.java
index decf0d8..bcffbdd 100644
--- a/src/main/java/cc/carm/plugin/userprefix/conf/prefix/PrefixConfig.java
+++ b/src/main/java/cc/carm/plugin/userprefix/conf/prefix/PrefixConfig.java
@@ -1,8 +1,10 @@
package cc.carm.plugin.userprefix.conf.prefix;
import cc.carm.lib.easyplugin.gui.configuration.GUIActionConfiguration;
+import cc.carm.lib.easyplugin.gui.configuration.GUIActionType;
import cc.carm.lib.easyplugin.utils.MessageUtils;
import cc.carm.lib.mineconfiguration.bukkit.value.item.PreparedItem;
+import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.manager.ServiceManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -97,7 +99,13 @@ public class PrefixConfig {
}
public void executeActions(@NotNull Player player) {
- this.actions.forEach(action -> action.executeAction(player));
+ this.actions.forEach(action -> {
+ if (action.getActionType() == GUIActionType.CONSOLE) { // 控制台执行命令必须在全局调度器中执行
+ Main.getInstance().getFoliaScheduler().runGlobal(false, () -> action.executeAction(player));
+ } else {
+ action.executeAction(player);
+ }
+ });
}
public boolean isVisible(Player player) {
diff --git a/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixChangeEvent.java b/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixChangeEvent.java
index 4c3272c..f65d256 100644
--- a/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixChangeEvent.java
+++ b/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixChangeEvent.java
@@ -2,6 +2,7 @@ package cc.carm.plugin.userprefix.event;
import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig;
+import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
@@ -61,8 +62,11 @@ public class UserPrefixChangeEvent extends UserPrefixEvent implements Cancellabl
@Nullable PrefixConfig before,
@NotNull PrefixConfig after,
@Nullable Consumer<@Nullable PrefixConfig> finish) {
- Main.getInstance().callSync(new UserPrefixChangeEvent(who, before, after))
- .thenAccept((e) -> Optional.ofNullable(finish).ifPresent(f -> f.accept(e.getAfter())));
+ UserPrefixChangeEvent event = new UserPrefixChangeEvent(who, before, after);
+ Main.getInstance().getFoliaScheduler().runGlobal(true, () -> {
+ Bukkit.getPluginManager().callEvent(event);
+ Optional.ofNullable(finish).ifPresent(f -> f.accept(event.getAfter()));
+ });
}
}
diff --git a/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixExpireEvent.java b/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixExpireEvent.java
index 8b70a7e..c653cb5 100644
--- a/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixExpireEvent.java
+++ b/src/main/java/cc/carm/plugin/userprefix/event/UserPrefixExpireEvent.java
@@ -2,6 +2,7 @@ package cc.carm.plugin.userprefix.event;
import cc.carm.plugin.userprefix.Main;
import cc.carm.plugin.userprefix.conf.prefix.PrefixConfig;
+import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
@@ -30,7 +31,7 @@ public class UserPrefixExpireEvent extends UserPrefixEvent {
}
public static void call(@NotNull Player player, @NotNull PrefixConfig currentPrefix) {
- Main.getInstance().callSync(new UserPrefixExpireEvent(player, currentPrefix));
+ Main.getInstance().getFoliaScheduler().runGlobal(true, () -> Bukkit.getPluginManager().callEvent(new UserPrefixExpireEvent(player, currentPrefix)));
}
}
diff --git a/src/main/java/cc/carm/plugin/userprefix/folia/FoliaScheduler.java b/src/main/java/cc/carm/plugin/userprefix/folia/FoliaScheduler.java
new file mode 100644
index 0000000..d3b0d82
--- /dev/null
+++ b/src/main/java/cc/carm/plugin/userprefix/folia/FoliaScheduler.java
@@ -0,0 +1,80 @@
+package cc.carm.plugin.userprefix.folia;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Entity;
+import org.bukkit.plugin.Plugin;
+
+public class FoliaScheduler {
+ private final Plugin plugin;
+ private final boolean folia;
+
+ public FoliaScheduler(Plugin plugin, boolean folia) {
+ this.plugin = plugin;
+ this.folia = folia;
+ }
+
+ public void runAsync(Runnable task) {
+ if (this.folia) {
+ this.runAsyncFolia(task);
+ } else {
+ this.runAsyncBukkit(task);
+ }
+ }
+
+ private void runAsyncBukkit(Runnable task) {
+ Bukkit.getScheduler().runTaskAsynchronously(this.plugin, task);
+ }
+
+ private void runAsyncFolia(Runnable task) {
+ Bukkit.getAsyncScheduler().runNow(this.plugin, t -> task.run());
+ }
+
+ /**
+ * Folia 上在实体所在的调度器上执行任务,或在 Bukkit 上同步执行任务
+ *
+ * @param entity 实体
+ * @param forceSync 若为 true,Bukkit 下强制同步运行;若为 false,Bukkit 下直接执行
+ * @param task 任务
+ * @see FoliaScheduler#runBukkit(boolean, Runnable)
+ * @see FoliaScheduler#runOnEntityFolia(Entity, Runnable)
+ */
+ public void runOnEntity(Entity entity, boolean forceSync, Runnable task) {
+ if (this.folia) {
+ this.runOnEntityFolia(entity, task);
+ } else {
+ this.runBukkit(forceSync, task);
+ }
+ }
+
+ private void runOnEntityFolia(Entity entity, Runnable task) {
+ entity.getScheduler().run(this.plugin, t -> task.run(), null);
+ }
+
+ /**
+ * Folia 上在全局调度器上执行任务,或在 Bukkit 上同步执行任务
+ *
+ * @param forceSync 若为 true,Bukkit 下强制同步运行;若为 false,Bukkit 下直接执行
+ * @param task 任务
+ * @see FoliaScheduler#runBukkit(boolean, Runnable)
+ * @see FoliaScheduler#runGlobalFolia(Runnable)
+ */
+ public void runGlobal(boolean forceSync, Runnable task) {
+ if (this.folia) {
+ this.runGlobalFolia(task);
+ } else {
+ this.runBukkit(forceSync, task);
+ }
+ }
+
+ private void runGlobalFolia(Runnable task) {
+ Bukkit.getGlobalRegionScheduler().execute(this.plugin, task);
+ }
+
+ private void runBukkit(boolean forceSync, Runnable task) {
+ if (forceSync) {
+ Bukkit.getScheduler().runTask(this.plugin, task);
+ } else {
+ task.run();
+ }
+ }
+}
diff --git a/src/main/java/cc/carm/plugin/userprefix/listener/UserPermListener.java b/src/main/java/cc/carm/plugin/userprefix/listener/UserPermListener.java
index 9c74a3f..67b6540 100644
--- a/src/main/java/cc/carm/plugin/userprefix/listener/UserPermListener.java
+++ b/src/main/java/cc/carm/plugin/userprefix/listener/UserPermListener.java
@@ -14,7 +14,7 @@ public class UserPermListener {
if (player == null) return;
UserPrefixAPI.getUserManager().checkPrefix(player, true);
if (PrefixSelectGUI.openingUsers.contains(player)) {
- Main.getInstance().getScheduler().run(() -> {
+ Main.getInstance().getFoliaScheduler().runOnEntity(player, true, () -> {
// 玩家权限更新,同步关闭其GUI,以令其重新打开刷新自己的前缀。
player.closeInventory();
PrefixSelectGUI.removeOpening(player);
diff --git a/src/main/java/cc/carm/plugin/userprefix/manager/UserManager.java b/src/main/java/cc/carm/plugin/userprefix/manager/UserManager.java
index a8410ae..5c8a7ad 100644
--- a/src/main/java/cc/carm/plugin/userprefix/manager/UserManager.java
+++ b/src/main/java/cc/carm/plugin/userprefix/manager/UserManager.java
@@ -32,7 +32,7 @@ public class UserManager {
@Nullable
public UserNameTag getNameTag(Player player) {
- if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) {
+ if (this.isNamePrefixEnabled()) {
if (nameTags.containsKey(player.getUniqueId())) {
return nameTags.get(player.getUniqueId());
} else {
@@ -53,7 +53,7 @@ public class UserManager {
public void initPlayer(Player player) {
checkPrefix(player, false);
- if (PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) {
+ if (this.isNamePrefixEnabled()) {
createNameTag(player);
updatePrefixView(player, true);
}
@@ -73,7 +73,7 @@ public class UserManager {
* @param loadOthers 是否为玩家更新其他人的前缀(一般用于加入游戏)
*/
public void updatePrefixView(Player player, boolean loadOthers) {
- if (!PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull()) return; //未启用的情况下,不需要进行任何操作。
+ if (!this.isNamePrefixEnabled()) return; //未启用的情况下,不需要进行任何操作。
UserNameTag tag = getNameTag(player);
if (tag == null) return; //未启用的情况下,不需要进行任何操作。
@@ -273,4 +273,7 @@ public class UserManager {
user.data().clear(NodeType.META.predicate(mn -> mn.getMetaKey().equals(META_KEY)));
}
+ private boolean isNamePrefixEnabled() {
+ return PluginConfig.FUNCTIONS.NAME_PREFIX.ENABLE.getNotNull() && !Main.getInstance().isOnFolia();
+ }
}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 805f71a..85ce41c 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -7,7 +7,8 @@ authors:
- SakuraGame
website: ${project.url}
description: ${project.description}
-api-version: 1.13
+api-version: 1.21.4
+folia-supported: true
depend:
- LuckPerms