World management + plot ownership plugin for Paper servers. Custom generators (void & plot), per-world generation overrides, schematic import (Bukkit + WorldEdit/FAWE), per-plot ownership with trusted/denied members and configurable flags, plot merging, in-game GUIs throughout, full developer API.
- World CRUD with three generation types:
DEFAULT(vanilla),VOID(empty),PLOT(grid-based plots with roads and walls) - Per-world plot generation overrides on
/mv create(plot size, road width, schematic to paste at every plot) - Schematic import — Bukkit
.nbt(native, no deps) + WorldEdit/FAWE.schem/.schematic(soft-dep) - Plot ownership — claim, unclaim, trust/untrust, deny/undeny, home, list
- Plot merging by player facing — joins adjacent same-owner plots, fills the road, removes walls; permission-capped group size
- 8 enforced plot flags —
pvp,mob-spawning,explosion,fire-spread,keep-inventory,entry,liquid-flow,ice-form-melt— per-plot override or default - Owner-customisable plot border via
/plot border <material>— visual signal that a plot is claimed (default border colour differs from unclaimed walls) - Per-world spawn locations + global spawn —
/spawnresolves global → current-world MV spawn → default world - Inventory-Framework GUIs everywhere —
/mv edit,/mv list,/plot menu(members + flags + home + unclaim) - MiniMessage translations with per-player locales (en_US, de_DE shipped) via JExTranslate / R18n
- Async-first design — all I/O returns
CompletableFuture; main-thread work is dispatched via Bukkit scheduler - Free and Premium editions: Free is capped at 3 worlds with
DEFAULT/VOID; Premium is unlimited and includesPLOT - Public API via
MultiverseProvider, registered on Bukkit'sServicesManager— exposes plot grid coords/bounds for external plugins - Backed by JEHibernate 3.0.3 — H2 by default, MySQL/PostgreSQL/Oracle/SQL Server supported
- Requirements
- Installation
- Configuration
- Commands
- Permissions
- Plot system
- Schematics
- Editions
- Developer API
- Building from Source
- Credits
- Java 21+
- Paper 1.19+ (developed against Paper API 1.21.x)
- JExDependency runtime loader (handles library injection)
- Optional: WorldEdit or FastAsyncWorldEdit — enables
.schem/.schematicschematic loading. Bukkit.nbtworks without it.
- Place the JExMultiverse
.jar(Free or Premium) into the server'splugins/folder. - Start the server. Configuration, database, command, schematic, and translation directories generate automatically.
- Create your first world with
/mv create <name> [environment] [type].
Plot-world generation defaults — applied to every plot world unless overridden at create time:
plot-world:
plot-size: 16 # edge length of each plot in blocks
road-width: 5 # width of road grid between plots
plot-height: 64 # y-coordinate of the plot surface
wall-height: 1 # 0 disables walls entirely
road-material: STONE_BRICKS
wall-material-unclaimed: STONE_BRICK_WALL # default for unclaimed plots
wall-material-claimed: MOSSY_STONE_BRICK_WALL # default after a plot is claimed
layers:
- { material: DIRT, min-y: 1, max-y: 62 }
- { material: GRASS_BLOCK, min-y: 63, max-y: 63 }
schematic-offset-x: 0 # paste offset relative to plot NW corner
schematic-offset-y: 1
schematic-offset-z: 0When a plot is claimed, JExMultiverse repaints the plot's perimeter with the
claimed wall material — by default MOSSY_STONE_BRICK_WALL so it visually
differs from the surrounding unclaimed STONE_BRICK_WALL. Owners can
override with /plot border <material> (see below). The wall stripes
between merged plots are cleared automatically.
Translation files live in plugins/JExMultiverse/translations/. Shipped languages: en_US, de_DE. New keys from plugin upgrades are merged into existing on-disk YAML at startup, so admin customizations are preserved. Add a new language by creating <locale>.yml and registering it in translation.yml under supportedLanguages. Reload in-game with /r18n reload.
Hibernate properties are in plugins/JExMultiverse/database/hibernate.properties. Default backend is H2 stored at plugins/JExMultiverse/database/jexmultiverse. Switch to MySQL, PostgreSQL, Oracle, or SQL Server by editing the connection settings. Schema migrations are automatic via hbm2ddl=update.
| Command | Description |
|---|---|
/mv |
Show command help |
/mv create <name> [env] [type] [plot_size] [road_width] [schematic] |
Create a new world. Last three args are PLOT-only |
/mv delete <world> |
Delete a world (unloads + removes files) |
/mv edit <world> |
Open the world editor GUI |
/mv teleport <world> |
Teleport to a world's spawn |
/mv load <world> |
Load a world from the database |
/mv list |
Paginated GUI of all managed worlds (text fallback for console) |
/mv applyschematic <world> [schematic] |
Re-paste a schematic into every plot in loaded chunks |
/mv help |
Show command help |
/mv create arguments:
name— world folder name (required)environment—NORMAL,NETHER, orTHE_END(default:NORMAL). Tab-completed.type—DEFAULT,VOID, orPLOT(default:DEFAULT). Tab-completed.plot_size— per-world plot edge length override (PLOT only)road_width— per-world road width override (PLOT only)schematic— schematic file name without extension, dropped intoplugins/JExMultiverse/schematics/(PLOT only)
/mv edit <world> opens a compact 3-row GUI with:
- Set spawn to your current location
- Toggle global-spawn designation (auto-clears it from any other world)
- Toggle PvP
- Cycle time of day (live world only — not persisted)
- Cycle weather: clear → rain → storm (live world only)
- Cycle difficulty: peaceful → easy → normal → hard (live world only)
- Save persisted fields to the database
| Command | Aliases | Description |
|---|---|---|
/spawn |
/pspawn |
Teleport to the resolved spawn location |
Resolution order: global-spawn world → current world's MV-set spawn → Bukkit default-world spawn. Each tier validates the world is loaded.
Aliases: /p, /plots.
| Command | Description |
|---|---|
/plot menu |
Open the plot management GUI |
/plot claim |
Claim the plot you're standing on |
/plot unclaim |
Release the plot you're standing on |
/plot info |
Show owner + member counts |
/plot trust <player> |
Allow another player to build |
/plot untrust <player> |
Remove a trusted player |
/plot deny <player> |
Block a player from this plot |
/plot undeny <player> |
Lift a deny |
/plot home [n] |
Teleport to your nth owned plot |
/plot list |
List your owned plots (count vs. cap) |
/plot flag <set|remove|list> [flag] [value] |
Manage plot flags |
/plot border [material] |
Change your plot's wall material (omit material to reset) |
/plot merge |
Merge with the plot you're facing |
/plot unmerge |
Split this plot off the merge group |
/plot help |
Show command help |
| Permission | Description |
|---|---|
jexmultiverse.command |
Use /multiverse (root) |
jexmultiverse.command.create |
Create worlds |
jexmultiverse.command.delete |
Delete worlds |
jexmultiverse.command.edit |
Open the world editor GUI |
jexmultiverse.command.teleport |
Teleport to managed worlds |
jexmultiverse.command.load |
Load worlds from the database |
jexmultiverse.command.list |
List managed worlds |
jexmultiverse.command.applyschematic |
Retroactively paste a schematic into a world's plots |
jexmultiverse.spawn |
Use /spawn |
| Permission | Description |
|---|---|
jexplots.command |
Use /plot (root) |
jexplots.command.claim |
Claim plots |
jexplots.command.unclaim |
Unclaim plots |
jexplots.command.info |
View plot info |
jexplots.command.trust / .untrust |
Manage trusted members |
jexplots.command.deny / .undeny |
Manage denied players |
jexplots.command.home |
Teleport to owned plots |
jexplots.command.list |
List owned plots |
jexplots.command.flag |
Manage plot flags |
jexplots.command.border |
Change a plot's wall material |
jexplots.command.merge / .unmerge |
Merge / unmerge plots |
jexplots.command.menu |
Open the plot menu GUI |
jexplots.claim.<n> |
Allow up to n claimed plots (highest matching wins) |
jexplots.claim.unlimited |
No claim cap |
jexplots.merge.<n> |
Allow merged groups up to n plots |
jexplots.merge.unlimited |
No merge cap |
jexplots.bypass.protect |
Staff bypass — ignore protection on all plots |
JExMultiverse ships a self-contained plot system for PLOT-type worlds. No PlotSquared dependency.
Stand on the plot you want to claim and run /plot claim. The claim limit is read from jexplots.claim.<n> permissions (default 1, unlimited available). The protection listener immediately gates block place/break, container interact, bucket use, fire ignition, and PvP between non-trusted players.
/plot trust <player>— let them build, break, interact, and use containers./plot deny <player>— store the role; full entry blocking is on the Phase 2D+ roadmap (currently surfaces in/plot infoand the GUI but doesn't gate movement yet).
Membership is per-plot. Merging plots A + B does not propagate trusted lists across the group — each plot keeps its own list.
Boolean overrides per plot. Default is the listed value when no override is set.
| Flag | Default | What it does |
|---|---|---|
pvp |
false |
When true, anyone can fight in this plot. When false (default), only owner ↔ trusted PvP is allowed. |
mob-spawning |
true |
When false, hostile mobs (creepers, zombies, phantoms, slimes, ghasts, etc.) don't naturally spawn. Spawn eggs / spawners still work. |
explosion |
false |
When false, blocks inside this plot survive creeper, TNT, wither, and end-crystal explosions. Other plots / terrain in the same blast still take damage. |
fire-spread |
false |
When false, fire won't spread or burn blocks. You can still light fires; they just don't propagate. |
keep-inventory |
false |
When true, players who die inside the plot keep their items + XP. Drops are cleared and dropped XP is zeroed. |
entry |
true |
When false, only the owner and trusted members can enter — others are pushed back when they cross the plot boundary. Denied players are always blocked regardless of this flag. |
liquid-flow |
false |
When false, water and lava can't flow into the plot — useful for protected builds adjacent to fluids. |
ice-form-melt |
false |
When false, ice and snow stay where they're placed — they neither melt in warm biomes nor form in cold ones. |
CLI: /plot flag set pvp true, /plot flag remove pvp, /plot flag list. GUI: /plot menu → flags slot (4×2 grid of toggle slots).
/plot border <material> repaints the plot's perimeter walls with the
chosen block. Tab completion suggests typical wall / fence materials
(stone_brick_wall, mossy_stone_brick_wall, cobblestone_wall,
oak_fence, iron_bars, glass, etc.) but accepts any solid block. Run
/plot border with no argument to reset to the default claimed material
from config.yml. Walls between merged plots stay cleared regardless.
Stand on your plot, face the adjacent plot you want to merge with, and run /plot merge. JExMultiverse uses player.getFacing() to pick the neighbor cell — no direction argument needed.
What happens:
- Both plots are tagged with a shared
mergedGroupId. - The road between them is filled with your plot's terrain layers.
- The 3-block walls facing each other are cleared.
- Other walls (around the rest of the merged group) stay.
/plot unmerge reverses the visual block updates between this plot and any adjacent group members and clears the group ID. If only one plot remains in the group afterwards, its group ID is cleared too (a group of one is just a standalone plot).
The combined group size is capped by jexplots.merge.<n> (highest matching) or jexplots.merge.unlimited. Default is 1 (no merging).
/plot menu opens a 3-row hub:
. . . . [owner head] . . . .
. [members] [flags] [home] [unclaim] .
. . . . . . . . .
- Owner head — player skin, lore shows owner / world / grid coords / trusted+denied counts / merged Y/N.
- Members — paginated player heads of trusted (green) and denied (red) members. Click an entry to remove the role.
- Flags — one toggle slot per flag. Click flips the value and updates the slot in place; lore reflects effective value + (default/override).
- Home — teleport to plot center, closes the menu.
- Unclaim — release the plot.
Adding members stays as /plot trust <player> and /plot deny <player> because the offline-player tab completion is smoother on the command line.
Drop schematic files into plugins/JExMultiverse/schematics/:
<name>.nbt— Bukkit's native structure block format. No external dependency.<name>.schem/<name>.schematic— WorldEdit / FastAsyncWorldEdit clipboard formats. Loaded only if WE/FAWE is installed; the boot log says which path is active.
Resolution order is .nbt → .schem → .schematic. The schematic pastes at every plot's NW corner during chunk generation, plus configurable offset (schematic-offset-x/y/z in config.yml — defaults 0,1,0 for "one block above plot surface").
/mv create village normal plot 24 5 my_house # uses my_house.* during chunkgen
/mv applyschematic village # retroactively paste into loaded chunks
/mv applyschematic village other_house # override the world's stored schematic name
Caveats:
- WE-format schematics can't paste during chunk generation (the edit-session API requires a real
World, not aLimitedRegion). Use/mv applyschematiconce chunks are loaded. .nbtschematics paste during generation AND retroactively, no manual step needed.
| Capability | Free | Premium |
|---|---|---|
| World limit | 3 | Unlimited |
DEFAULT generator |
✅ | ✅ |
VOID generator |
✅ | ✅ |
PLOT generator |
❌ | ✅ |
| Plot ownership / flags / merging | ❌ | ✅ |
| Schematic import | ❌ | ✅ |
| World editor GUI | ✅ | ✅ |
/spawn + global spawn |
✅ | ✅ |
| Developer API | ✅ | ✅ |
JExMultiverse registers MultiverseProvider with Bukkit's ServicesManager.
import de.jexcellence.multiverse.api.JExMultiverseAPI;
import de.jexcellence.multiverse.api.MultiverseProvider;
import de.jexcellence.multiverse.api.PlotCoord;
import de.jexcellence.multiverse.api.PlotBounds;
// Obtain the provider
MultiverseProvider mv = JExMultiverseAPI.get();
// World snapshots — all return CompletableFuture
mv.getWorld("my_world").thenAccept(opt -> { /* MVWorldSnapshot or empty */ });
mv.getGlobalSpawnWorld().thenAccept(opt -> { /* ... */ });
mv.getAllWorlds().thenAccept(list -> { /* ... */ });
mv.hasMultiverseSpawn("my_world").thenAccept(present -> { /* ... */ });
// Teleport using the spawn-resolution chain
mv.spawn(player).thenAccept(success -> { /* ... */ });
// Plot grid lookups (synchronous — listener-safe)
mv.plotAt(player.getLocation()).ifPresent(coord -> {
// coord.world(), coord.gridX(), coord.gridZ()
});
mv.plotBounds("city", 3, 5).ifPresent(b -> {
// b.minX/Z, b.maxX/Z, b.surfaceY, b.size(), b.centerX(), b.centerZ()
});
if (mv.isRoadOrBorder(loc)) { /* loc is on a plot road */ }
// Plot ownership lookups (synchronous — listener-safe)
mv.plotOwnership(loc).ifPresent(o -> {
// o.ownerUuid(), o.ownerName(), o.mergedGroupId(), o.claimedAt()
});
// Protection check — true if the player can build here under JExMultiverse
// plot rules (owner / trusted / bypass / unclaimed).
boolean allowed = mv.canBuild(player, loc);
// Effective flag value at a location — empty if no plot is claimed there.
mv.getPlotFlag(loc, "pvp").ifPresent(pvpEnabled -> { /* ... */ });The plot-grid + ownership API is intended for external plugins that want to integrate with JExMultiverse plot worlds — claim systems, plot-merging tools, region overlays, anti-grief integrations, etc. It exposes stable (world, gridX, gridZ) identifiers, exact bounds, ownership snapshots, and effective flag values without forcing consumers to know the underlying generation parameters or schema.
MVWorldSnapshot, PlotCoord, PlotBounds, and PlotOwnership are all Java 21 records.
Heavy work happens off the main thread; schedule any Bukkit API calls back onto the primary thread.
# Publish local dependencies first
./gradlew :JExCommand:publishToMavenLocal
./gradlew :JExTranslate:publishToMavenLocal
./gradlew :JExDependency:publishToMavenLocal
# Build both editions
./gradlew :JExMultiverse:buildAll
# Or individually
./gradlew :JExMultiverse:jexmultiverse-free:shadowJar
./gradlew :JExMultiverse:jexmultiverse-premium:shadowJar
# Publish to local Maven
./gradlew :JExMultiverse:publishLocalArtifacts:
jexmultiverse-free/build/libs/JExMultiverse-<version>-Free.jarjexmultiverse-premium/build/libs/JExMultiverse-<version>-Premium.jar
- Author: JExcellence — https://jexcellence.de
- Runtime dependency injection: JExDependency
- ORM layer: JEHibernate (Hibernate 7.x)
- GUI framework: InventoryFramework
- Command framework: JExCommand 2.0
- i18n: JExTranslate / R18n
- Schematic loading: Bukkit Structure API + WorldEdit / FastAsyncWorldEdit (optional)