From eab9b2385ce3c086a53c34b65b8a20b4762c84e7 Mon Sep 17 00:00:00 2001 From: flowerinsnow Date: Mon, 5 May 2025 22:17:40 +0800 Subject: [PATCH] feat: folia support --- pom.xml | 20 ++++- .../java/cc/carm/plugin/userprefix/Main.java | 25 +++++- .../plugin/userprefix/conf/PluginConfig.java | 2 +- .../userprefix/conf/prefix/PrefixConfig.java | 10 ++- .../event/UserPrefixChangeEvent.java | 8 +- .../event/UserPrefixExpireEvent.java | 3 +- .../userprefix/folia/FoliaScheduler.java | 80 +++++++++++++++++++ .../userprefix/listener/UserPermListener.java | 2 +- .../userprefix/manager/UserManager.java | 9 ++- src/main/resources/plugin.yml | 3 +- 10 files changed, 147 insertions(+), 15 deletions(-) create mode 100644 src/main/java/cc/carm/plugin/userprefix/folia/FoliaScheduler.java 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