指南
如何製作 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 產生這個