ExooQueue – Queue Management Plugin (Paper 1.21)

概述
- ExooQueue 限制了主世界中的玩家数量,并将超出限制的玩家排队到等待世界。
- 玩家可以看到他们的队列位置和 ETA。
- VIP(权限或 /vip 命令)可以跳过队列。
- 命令和动作是可配置的。动作可以在玩家或控制台身份运行,并支持 %player_name% 和 PlaceholderAPI(如果已安装)。
- SQLite 已初始化以供未来持久化(尚未实际使用)。
要求
- Multiverse core(用于定义等待和其他世界)
- 服务器:Paper 1.21.x
- Java:21 (JDK/JRE)
- 可选:PlaceholderAPI(用于动作中的高级占位符)
- 可选:如果使用动作中的命令,例如“mvtp”,则需要一个世界管理插件(例如 Multiverse-Core)
文件
- src/main/resources/plugin.yml → Bukkit 命令/权限声明
- src/main/resources/config.yml → 插件配置(世界、队列、命令 + 动作)
- src/main/java/.../ExooQueuePlugin.java → 主插件类
- build.gradle, settings.gradle → Gradle 构建文件
安装 (使用构建的 JAR)
1) 将 build/libs/ExooQueue-1.0.0.jar 复制到你的 Paper 服务器的 "plugins" 文件夹中。
2) 服务器启动一次以生成 config.yml。
3) 停止服务器并在 plugins/ExooQueue/config.yml 中进行必要的编辑。
4) 再次启动服务器。
构建 (如果需要重建)
- 从项目根目录: ./gradlew build (Linux/macOS) 或 .\\gradlew.bat build (Windows)
- 输出 JAR:build/libs/ExooQueue-1.0.0.jar
核心概念
- 主世界:玩家想要加入的目标世界(例如,“world”)。
- 等待世界:排队的玩家等待的 Lobby。
- 最大玩家数:当主世界达到这个数字时,其他玩家将被排队。
- VIP 跳过:具有 "exooqueue.vip" 权限或通过 /vip 添加的玩家可以跳过队列。操作员 (op) 默认跳过。
- 动作:当玩家允许进入主世界时运行的一系列命令。您可以以玩家或控制台的身份运行单独的命令。
配置 (config.yml)
键
- author: 自由格式字符串。
- max-players: 整数。主世界中允许的最大玩家数。
- main-world: 目标世界的世界名称。
- wait-world: 队列 Lobby 的世界名称。
- wait-time-per-player: 每次队列位置计算 ETA 的整数秒数。
- commands: 命令名称 → 设置 (描述、权限、vip-权限、动作) 的映射。
示例 (默认)
author: "Moin"
max-players: 10
main-world: "world"
wait-world: "wait"
wait-time-per-player: 10
commands:
lifesteal:
description: "加入 lifesteal 队列"
permission: "exooqueue.lifesteal"
vip-permission: "exooqueue.vip"
actions:
player:
- "say %player_name% 加入 lifesteal!"
console:
- "mvtp %player_name% world"
vip:
description: "使玩家 VIP 跳过队列"
permission: "exooqueue.vip"
actions:
player: []
console: []
动作中的占位符
- %player_name% 始终替换为玩家名称。
- 如果安装了 PlaceholderAPI,则也会处理所有 PAPI 占位符。
命令 (用户可见)
- /lifesteal
描述:尝试加入主世界。如果已满,将玩家添加到队列并将他们传送到等待世界。
权限:exooqueue.lifesteal (默认:通过 plugin.yml 启用)
- /vip
描述:授予玩家临时的 VIP 跳过权限(持久到服务器重启;未保存到数据库)。
权限:exooqueue.vip (默认:op)
权限
- exooqueue. → 运行该命令所需的权限(例如,exooqueue.lifesteal)
- exooqueue.vip → 跳过队列并使用 /vip
- 操作员也默认跳过队列。
队列工作原理
1) 玩家运行加入命令 (例如,/lifesteal)。
2) 如果 VIP/op 或主世界有容量,则配置的动作立即运行(例如,传送),并且玩家加入。
3) 如果已满且不是 VIP,则将玩家添加到内存队列并将他们传送到等待世界。
4) 后台任务每 5 秒检查一次:如果可用槽数,则处理下一个排队的玩家并运行其动作。
5) 显示给玩家的 ETA 是位置 × wait-time-per-player。
添加自定义加入命令
注意:命令必须在 plugin.yml 中声明才能被 Bukkit 识别。然后,在 config.yml 中配置该行为。
步骤
1) 编辑 src/main/resources/plugin.yml 并添加一个命令块:
commands:
myworld:
description: 加入 myworld 队列
permission: exooqueue.myworld
permission-message: 你没有使用此命令的权限。
2) 编辑 src/main/resources/config.yml 并添加相应的配置:
commands:
myworld:
description: "加入 myworld 队列"
permission: "exooqueue.myworld"
vip-permission: "exooqueue.vip"
actions:
player:
- "say %player_name% 正在加入 myworld!"
console:
- "mvtp %player_name% myworld"
3) 重新启动服务器(或完全重新加载插件)以注册新的命令和加载配置。
关于队列处理的重要说明
- 默认的队列处理使用“lifesteal”命令的动作从队列中移动玩家。
- 如果您有多个不同的加入命令/世界,您应该:
a) 为所有队列使用相同的动作(将每个人指向同一个目的地),或
b) 更新代码以跟踪每个玩家使用的命令,并在处理队列时运行相应的动作。
如果您需要选项 (b),请考虑增强代码以存储一个排队的玩家 UUID → 命令名称的映射,并修改 processQueue() 以查找并运行该命令的动作。
更改世界和生成点
- 确保在 config.yml 中列出的世界(main-world、wait-world)存在于您的服务器上。
- 使用游戏内命令(例如 /setworldspawn)或您的世界管理插件设置等待世界生成点。
- 如果您在动作中使用 Multiverse-Core 命令(例如 mvtp),请安装该插件并确保控制台/玩家权限正确。
SQLite 数据库
- 插件创建 plugins/ExooQueue/queue.sqlite 和一个表 "queue" (uuid TEXT PRIMARY KEY, position INTEGER)。
- 当前版本尚未在重启后持久化队列内容。未来更新可能会使用它进行持久化。
重新加载配置
- 此版本在启动时读取配置。 要应用更改:
- 停止并启动服务器,或
- 使用完整的服务器重新加载(谨慎使用)(/reload confirm)。 建议重新启动。
故障排除
- 找不到命令:确保命令存在于 plugin.yml 中并且 config.yml 中有一个匹配的条目。
- 玩家未传送:验证您的动作是否引用了正确的世界,并且任何必需的插件(例如 Multiverse-Core)都已安装。
- 占位符未替换:安装 PlaceholderAPI 以使用高级占位符。 %player_name% 始终有效。
- VIP 未保存:/vip 是临时的,并在重启时清除。 为了永久 VIP,请通过您的权限插件授予 exooqueue.vip 权限。
- 构建问题:使用 Java 21 并且确保可以访问 Paper 存储库。提供的 Gradle 配置针对 Paper 1.21.x。
路线图想法(如果您扩展插件)
- 在重启后将队列和 VIP 列表持久化到 SQLite。
- 每个命令的队列和处理排队玩家的动作。
- 添加 /queue status、/queue leave 和管理控件。
- 配置重新加载命令。
- 每个世界的限制(具有各自容量的 main-world 列表)。
快速参考
- 主命令:/lifesteal
- VIP 命令:/vip
- 配置路径:plugins/ExooQueue/config.yml
- 权限:exooqueue.,exooqueue.vip
- 世界:main-world (目的地),wait-world (队列 Lobby)
支持
- 如果您需要更新代码以支持每个命令的队列或持久化,请提供您期望的行为,我们可以相应地扩展插件。