指南
如何制作 Folia 插件
更新于 2026年10月18日
Folia 是 Paper 的一个分支,它把世界划分成区域,并在不同线程上分别运行它们的 tick,让大型服务器能用上多个 CPU 核心。这里不再有唯一的主线程,常用的 Bukkit 调度器也因此失效。Folia 插件就是按这种模型编写的 Paper 插件,并且必须在 plugin.yml 中声明这一点。
一个包含 Folia 所需时间细节的示例。
用 Codexe 生成这个分步说明
1.确认你真的需要 Folia
Folia 适合玩家很多、分散在世界各处的服务器。大多数服务器跑的是 Paper;很多热门插件不支持 Folia,所以先检查你依赖的那些插件。
2.基于 Folia API 构建
在 Maven 或 Gradle 项目中,使用 PaperMC 仓库中对应你版本的
folia-api依赖,作用域为provided。3.替换 Bukkit 调度器
Bukkit.getScheduler()在 Folia 上无法使用。某个位置上的工作用区域调度器,针对玩家或生物的工作用实体调度器,全世界范围的任务用全局区域调度器,I/O 用异步调度器。4.只在所属区域内操作对象
只在拥有某个方块或实体的线程上修改它。用
teleportAsync代替teleport,并在修改目标之前先调度到它所在的区域。5.声明支持 Folia
在
plugin.yml中加上folia-supported: true。没有它,Folia 会拒绝加载插件。6.在 Folia 服务器上测试
编译通过只能证明代码能基于 Folia API 构建,不能证明它是线程安全的。在 Folia 测试服务器上运行它,并让几名玩家分散在不同地方。
四种调度器
| 调度器 | 获取方式 | 用途 |
|---|---|---|
| 区域 | Bukkit.getRegionScheduler() | 在世界中某个位置上的工作:放置方块、生成实体 |
| 实体 | entity.getScheduler() | 针对某个玩家或生物的工作,会跟随它跨越区域 |
| 全局区域 | Bukkit.getGlobalRegionScheduler() | 世界时间、天气,以及与位置无关的事情 |
| 异步 | Bukkit.getAsyncScheduler() | 数据库、文件、网络请求,绝不操作世界 |
通常会出问题的地方
- 针对所有玩家的重复任务:遍历所有在线玩家的单个循环不再可行;改为在每个玩家的实体调度器上分别调度任务。
- 传送和预热:“3 秒后传送”需要用实体调度器和
teleportAsync。 - 共享数据:在多个区域中使用的映射表和计数器必须是线程安全的,例如使用并发集合。
- 依赖:调用 Bukkit 调度器的库在 Folia 上会抛出
UnsupportedOperationException。
一个插件同时支持 Paper 和 Folia
在当前版本中,区域、实体、全局和异步调度器也是 Paper API 的一部分,所以只使用这些调度器并声明 folia-supported: true 的插件,可以同时在 Paper 和 Folia 上运行。这通常是最好的目标:一个 .jar 适用于所有服务器。
用 Codexe
选择 Folia 类型。生成的插件使用区域、实体、全局区域和异步调度器安排工作,声明 folia-supported: true,并用 Maven 基于 Folia API 构建。在标记为就绪之前,它会被编译和检查。
在需求中写明时间细节(“每分钟对每个在线玩家”“3 秒后传送”):Folia 代码与普通代码差别最大的就是这里。“立即试用”暂时还不支持 Folia 服务器,所以请在你自己的 Folia 服务器上测试 .jar。
常见问题
Paper 插件能在 Folia 上运行吗?
只有专门为它编写并声明了 folia-supported: true 的才行。使用 Bukkit 调度器的普通 Paper 插件会被拒绝加载或运行失败。
Folia 插件能在 Paper 上运行吗?
能,只要它只用 Paper 也有的 API,在当前的 Paper 版本中这也包括 Folia 的调度器。
我的 Folia 插件抛出了和调度器有关的异常
有些代码(通常来自某个库)仍在使用 Bukkit 调度器。在项目聊天中要求把它改到区域调度器或实体调度器上。
制作 Folia 插件
这条提示词打开后即可直接发送:
“一个名为 RTP 的 Folia 1.21.4 插件:/rtp 在 3 秒预热(移动即取消)后,把玩家传送到 5000 格范围内的随机安全位置,使用实体调度器和 teleportAsync,每个玩家冷却 10 分钟并保存在 SQLite 中,folia-supported: true,半径、冷却和消息在 config.yml 中。”
用 Codexe 生成这个