Skip to content

Lorn87/RegionDispatcher

Repository files navigation

RegionDispatcher

Build

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.

Features

  • 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 ConcurrentHashMap and AtomicInteger.
  • Visual debug. /regionspawn show <name> outlines a region with particles for 30 seconds.
  • MiniMessage support for the dispatch and full-lobby messages.

Requirements

  • Folia (or Paper) 1.21.x with the modern paper-plugin loader
  • Java 21 at runtime

Installation

  1. Download RegionDispatcher-1.0.0.jar from the releases page (or build from source — see below).
  2. Drop it into your server's plugins/ folder.
  3. Start the server once to generate plugins/RegionDispatcher/config.yml.
  4. Edit the config (or just leave the defaults) and restart.
  5. In game, use /regionspawn add <name> at each spawn point to register your regions.

Configuration

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.

Usage workflow

The recommended way to set up your lobby:

  1. Build (or paste with WorldEdit/FAWE) your lobby at the first location.
  2. Walk to the spot where players should spawn, face the direction you want them to look at.
  3. /regionspawn add lobby_1
  4. Move 1000 blocks (or however far you want) and paste a second copy.
  5. Walk to its spawn, face the same direction.
  6. /regionspawn add lobby_2
  7. Repeat for as many copies as you need.
  8. /regionspawn list to verify everything is registered.
  9. /regionspawn show lobby_1 to outline a region with particles and verify the bounds visually.

Now reconnect — you'll be dispatched to one of the registered zones automatically.

Commands

/regionspawn (alias /rspawn)

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

/dispatch (aliases /regiondispatcher, /rd)

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

Permissions

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.

Lobby protection details

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.

Building from source

git clone https://github.com/Lorn87/RegionDispatcher.git
cd RegionDispatcher
./gradlew build

The 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.

How it works

  1. On PlayerJoinEvent, if the player is in the lobby world, they are scheduled (via the entity scheduler) for a dispatch on the next tick.
  2. The DispatchManager picks the best region according to the configured strategy, increments its in-memory counter, and asynchronously teleports the player to the region's spawn.
  3. A repeating async task runs recount() every recount-interval ticks: 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.
  4. On PlayerQuitEvent, the player's region is detected and the corresponding counter is decremented immediately.
  5. 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).
  6. The protection listener intercepts a list of harmful events in the lobby world and cancels them unless the player has regiondispatcher.bypass.

Releases

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.0

The release workflow will build the jar, attach it to a GitHub release, and generate release notes from the commits since the previous tag.

License

This plugin is released as-is by Lorn87. Use it freely on your servers.

About

A standalone Folia plugin that distributes lobby players across multiple zones to take advantage of per-region multi-threading. No WorldGuard, no WorldEdit, no external dependencies.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages