A standalone Folia plugin that distributes incoming players across multiple lobby zones to take advantage of Folia's per-region multi-threading.
When several hundred players land in the same area on a Folia server, only one region thread does all the work and the other CPU cores stay idle. By splitting your lobby into several copies of the same build (placed at fixed offsets) and dispatching players between them, RegionDispatcher lets Folia parallelize the load and keeps the server responsive even with very high player counts.
The plugin has no external dependencies: no WorldGuard, no WorldEdit, nothing. Zones are defined by a simple radius around a spawn point, and an in-game command lets you create them just by standing where you want and typing one command.
- Automatic dispatch on join. Every player joining the lobby world is teleported to one of the configured regions.
- Three dispatch strategies.
LEAST_FILLED— sends the player to the region with the fewest occupants (default).ROUND_ROBIN— alternates between regions in declared order.RANDOM— picks a random region from those that are not full.
- Per-region capacity. Configurable hard cap; once a region is full, new players go elsewhere.
- In-game region creation.
/regionspawn add <name>saves your current position as a new region's spawn — no YAML editing, no coordinate math. - Lobby protection. Players in the lobby world cannot break/place blocks, interact with containers, take damage, drop items, lose hunger, PvP, or use buckets/projectiles. Only commands and movement are allowed. Bypassable with a permission node.
- Void rescue. Players falling below a configurable Y threshold are automatically re-dispatched to a free region instead of dying.
- Periodic recount. Player counts are refreshed asynchronously to handle teleports made by other plugins.
- Folia-safe. All teleports use the entity scheduler. Counters are based on
ConcurrentHashMapandAtomicInteger. - Visual debug.
/regionspawn show <name>outlines a region with particles for 30 seconds. - MiniMessage support for the dispatch and full-lobby messages.
- Folia (or Paper) 1.21.x with the modern paper-plugin loader
- Java 21 at runtime
- Download
RegionDispatcher-1.0.0.jarfrom the releases page (or build from source — see below). - Drop it into your server's
plugins/folder. - Start the server once to generate
plugins/RegionDispatcher/config.yml. - Edit the config (or just leave the defaults) and restart.
- In game, use
/regionspawn add <name>at each spawn point to register your regions.
The default config.yml:
world: "world"
max-per-region: 50
strategy: LEAST_FILLED
recount-interval: 100
default-region-size: 200
default-region-y-min: -64
default-region-y-max: 320
enable-protection: true
void-threshold: -64
dispatch-message: "<gray>Vous avez ete place dans la zone <gold>{region}</gold> <gray>(<white>{count}/{max}</white>)"
full-message: "<red>Le lobby est complet ! Reessayez dans quelques instants."
regions: {}| Key | Description |
|---|---|
world |
The Bukkit world that contains the lobby. |
max-per-region |
Hard player cap per region. |
strategy |
LEAST_FILLED, ROUND_ROBIN, or RANDOM. |
recount-interval |
Number of ticks between async recounts. |
default-region-size |
Default radius (in blocks) for regions created via /regionspawn add. A region becomes a (2*radius) x (2*radius) square centered on its spawn. |
default-region-y-min |
Lower Y bound applied to every region. Remove this key to ignore Y. |
default-region-y-max |
Upper Y bound applied to every region. Remove this key to ignore Y. |
enable-protection |
If true, players in the lobby world cannot break blocks, drop items, take damage, etc. |
void-threshold |
Players falling below this Y are auto-dispatched to a free region. |
dispatch-message |
MiniMessage shown after a player is dispatched. Placeholders: {region}, {count}, {max}. |
full-message |
MiniMessage shown when every region is at capacity. |
regions |
Map of region id → spawn data. Managed automatically by /regionspawn add. |
The recommended way to set up your lobby:
- Build (or paste with WorldEdit/FAWE) your lobby at the first location.
- Walk to the spot where players should spawn, face the direction you want them to look at.
/regionspawn add lobby_1- Move 1000 blocks (or however far you want) and paste a second copy.
- Walk to its spawn, face the same direction.
/regionspawn add lobby_2- Repeat for as many copies as you need.
/regionspawn listto verify everything is registered./regionspawn show lobby_1to outline a region with particles and verify the bounds visually.
Now reconnect — you'll be dispatched to one of the registered zones automatically.
The interactive region management command. Requires regiondispatcher.admin.
| Subcommand | Description |
|---|---|
/regionspawn |
Show usage |
/regionspawn add <name> |
Save your current position (with yaw/pitch) as the spawn of the named region. Updates the region if it already exists. |
/regionspawn remove <name> |
Delete a region from the config |
/regionspawn list |
List all regions with their current player count and spawn coordinates |
/regionspawn tp <name> |
Teleport yourself to a region's spawn |
/regionspawn show <name> |
Display the region's bounds with particles for 30 seconds |
/regionspawn reload |
Reload the config file |
Status and admin operations. Requires regiondispatcher.admin.
| Subcommand | Description |
|---|---|
/dispatch or /dispatch status |
Show current strategy, max per region, and live player counts |
/dispatch reload |
Reload the config and trigger an immediate recount |
/dispatch recount |
Force an immediate recount and print the result |
/dispatch send <player> <region-id> |
Manually teleport a player to a specific region's spawn |
| Permission | Default | Description |
|---|---|---|
regiondispatcher.admin |
op | Access to all /dispatch and /regionspawn subcommands |
regiondispatcher.bypass |
false | Bypass lobby protection (block break/place, drops, damage, etc.) |
regiondispatcher.bypass is explicitly disabled by default for everyone, including OPs. Grant it manually via your permissions plugin (e.g. lp user <name> permission set regiondispatcher.bypass true) to staff members who need to build in the lobby.
When enable-protection: true, players in the lobby world cannot:
- Break or place blocks
- Interact with containers (chests, furnaces, hoppers, droppers, dispensers, brewing stands, anvils…)
- Open or interact with doors, trapdoors, fence gates, buttons, levers, jukeboxes, note blocks
- Empty or fill buckets
- Drop items
- Lose hunger (food level is locked at 20)
- Take any damage (fall, mob, void, suffocation, etc.)
- PvP each other
- Ignite blocks
- Break item frames or paintings
- Throw projectiles (eggs, snowballs, ender pearls, etc.)
The only things players can do are: move, chat, run commands, open custom plugin GUIs, and interact with custom entities (NPCs, hologram clicks, etc.).
Players with the regiondispatcher.bypass permission are exempt from all of the above.
git clone https://github.com/Lorn87/RegionDispatcher.git
cd RegionDispatcher
./gradlew buildThe shaded jar will be in build/libs/RegionDispatcher-1.0.0.jar.
The build only needs Paper API as a compileOnly dependency, which is fetched from the PaperMC Maven repository automatically.
- On
PlayerJoinEvent, if the player is in the lobby world, they are scheduled (via the entity scheduler) for a dispatch on the next tick. - The
DispatchManagerpicks the best region according to the configured strategy, increments its in-memory counter, and asynchronously teleports the player to the region's spawn. - A repeating async task runs
recount()everyrecount-intervalticks: it walks every player in the lobby world, checks which region's bounds they fall inside, and rebuilds the counter map. This corrects any drift caused by other plugins teleporting players around. - On
PlayerQuitEvent, the player's region is detected and the corresponding counter is decremented immediately. - If a player crosses the void threshold (default
y = -64), they are immediately re-dispatched to a free region (with a 2-second cooldown to prevent loops). - The protection listener intercepts a list of harmful events in the lobby world and cancels them unless the player has
regiondispatcher.bypass.
This plugin uses GitHub Actions to automatically build a jar on every push and to publish a release whenever a v* tag is pushed.
To cut a new release locally:
git tag -a v1.1.0 -m "RegionDispatcher 1.1.0"
git push origin v1.1.0The release workflow will build the jar, attach it to a GitHub release, and generate release notes from the commits since the previous tag.
This plugin is released as-is by Lorn87. Use it freely on your servers.