Skip to content

Folia Support

Cyrusbye720 edited this page Aug 5, 2026 · 6 revisions

DZEconomy Banner

Folia Support

How DZEconomy runs on Folia, Paper's region-based multithreading fork.


What Folia Changes

Folia divides the world into independent regions that tick in parallel on multiple threads, instead of one main thread.

Aspect Paper Folia
Threading One main thread Multiple region threads
Scheduling Bukkit.getScheduler() Global, region, and entity schedulers
Thread safety Not required Required
Compatibility Any plugin Only Folia-aware plugins

How DZEconomy Adapts

DZEconomy routes all scheduling through FoliaAdapter, a utility class that detects Folia at startup and picks the right scheduler.

Detection

On class load, DZEconomy checks for io.papermc.paper.threadedregions.RegionizedServer. When found, it initializes the Folia scheduler methods through reflection.

The Schedulers

Scheduler Use Case DZEconomy Usage
GlobalRegionScheduler Tasks not tied to a location or entity Auto-save, daily reset, update checks, combat tag cleanup
RegionScheduler Tasks for a specific location Location-bound work
EntityScheduler Tasks for a specific entity Player notifications, reward delivery
AsyncScheduler Off-thread work Database operations

FoliaAdapter API

FoliaAdapter.isFolia()                              // true when running Folia
FoliaAdapter.runTask(plugin, () -> { ... })         // next tick, global/main thread
FoliaAdapter.runTaskAsynchronously(plugin, () -> { ... })
FoliaAdapter.runTaskLater(plugin, () -> { ... }, delayTicks)
FoliaAdapter.runTaskTimer(plugin, () -> { ... }, delayTicks, periodTicks)
FoliaAdapter.runTaskTimerAsynchronously(plugin, () -> { ... }, delayTicks, periodTicks)
FoliaAdapter.runAtEntity(plugin, entity, () -> { ... })
FoliaAdapter.runAtLocation(plugin, location, () -> { ... })
FoliaAdapter.cancelTasks(plugin)

Every call returns a FoliaTask handle with a single cancel() method, no matter which scheduler backed it.

Thread Safety

All balance-modifying operations are safe from any thread:

  • Per-player locks — each player has their own lock
  • Atomic transfers — a two-phase commit keeps transfers consistent
  • Concurrent collections — data caches use ConcurrentHashMap
  • Async storage — database writes run off the tick loop

Feature Compatibility on Folia

Feature Status
Multi-currency balances Full support
Player-to-player transfers Full support
Payment requests Full support
Baltop Full support
Mob rewards Full support
PVP loot Full support
Combat tag Full support
Auto-save Full support
MySQL storage Full support
SQLite storage Full support
PlaceholderAPI Full support
LuckPerms integration Full support
Rank multipliers Full support
Currency conversion Full support
Payall Full support
Update checker Full support
Config reload Full support

Known Limitations

Minimum Tick Delay

Folia schedulers require a minimum delay of 1 tick for delayed and repeating tasks. FoliaAdapter clamps all delays to at least 1.

Entity Retirement

When an entity retires, its scheduled tasks are cancelled. DZEconomy handles this without errors: combat tag tasks clean up on quit, player data saves asynchronously on disconnect, and the retirement callback is a no-op.

No Main Thread

Folia has no single main thread. Code that shipped expecting a main thread must run on the owning region's thread. The adapter routes runAtEntity, runAtLocation, and runTask accordingly.

Bytecode Detection

Because the Folia scheduler classes only exist on Folia, the adapter loads them through reflection at startup. Standard Bukkit servers never touch that code path, so they get no class-loading errors.


Performance on Folia

Folia helps servers where many players spread across different areas:

Metric Paper (100 players) Folia (100 players)
TPS Can dip below 20 Stable at 20
Economy operations Fast, one thread Fast, parallel regions
Auto-save impact Possible lag spike Distributed
Mob reward processing Sequential Parallel by region

Balance lookups hit the in-memory cache in constant time on both platforms. Balance changes only contend on the same player's lock, so different players never block each other.

Tuning for Folia

  1. Use MySQL for multi-server networks. SQLite is fine for a single Folia server.
  2. Keep the auto-save interval reasonable. Folia spreads the load, but fewer saves still helps.
  3. Disable features you do not use. PVP loot and combat tag off means fewer scheduled tasks.

Troubleshooting

"Not on the main thread" errors

No such thing exists on Folia. If you see this from another plugin, that plugin calls Bukkit.getScheduler() directly and will not work on Folia. DZEconomy never does.

Tasks not executing

Check whether the entity or location is still valid. A retired entity never runs its scheduled tasks. Confirm console shows DZEconomy enabled normally.

Performance regression

  1. Confirm your Folia build is current (1.19.4+).
  2. Check whether another plugin is the bottleneck, not DZEconomy.
  3. Raise auto-save.interval if the save tasks contend with gameplay regions.

See Version Coverage for supported Folia versions.


Quick Links

DZEconomy GitHub • Discord Support • Wiki Home

Developed by DemonZ Development

Clone this wiki locally