Skip to content

Repository files navigation

JExMultiverse

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 - /spawn resolves 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 includes PLOT
  • Public API via MultiverseProvider, registered on Bukkit's ServicesManager - exposes plot grid coords/bounds for external plugins
  • Backed by JEHibernate 3.0.3 - H2 by default, MySQL/PostgreSQL/Oracle/SQL Server supported

Table of Contents

Requirements

  • Java 21+
  • Paper 1.19+ (developed against Paper API 1.21.x)
  • JExDependency runtime loader (handles library injection)
  • Optional: WorldEdit or FastAsyncWorldEdit - enables .schem/.schematic schematic loading. Bukkit .nbt works without it.

Installation

  1. Place the JExMultiverse .jar (Free or Premium) into the server's plugins/ folder.
  2. Start the server. Configuration, database, command, schematic, and translation directories generate automatically.
  3. Create your first world with /mv create <name> [environment] [type].

Configuration

config.yml

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 blocksroad-width: 5# width of road grid between plotsplot-height: 64# y-coordinate of the plot surfacewall-height: 1# 0 disables walls entirelyroad-material: STONE_BRICKSwall-material-unclaimed: STONE_BRICK_WALL # default for unclaimed plotswall-material-claimed: MOSSY_STONE_BRICK_WALL # default after a plot is claimedlayers:
- { 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 cornerschematic-offset-y: 1schematic-offset-z: 0

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

Translations

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.

Database

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.

Commands

World commands (/mv)

CommandDescription
/mvShow 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 listPaginated GUI of all managed worlds (text fallback for console)
/mv applyschematic <world> [schematic]Re-paste a schematic into every plot in loaded chunks
/mv helpShow command help

/mv create arguments:

  • name - world folder name (required)
  • environment - NORMAL, NETHER, or THE_END (default: NORMAL). Tab-completed.
  • type - DEFAULT, VOID, or PLOT (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 into plugins/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

Spawn command

CommandAliasesDescription
/spawn/pspawnTeleport 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.

Plot commands (/plot)

Aliases: /p, /plots.

CommandDescription
/plot menuOpen the plot management GUI
/plot claimClaim the plot you're standing on
/plot unclaimRelease the plot you're standing on
/plot infoShow 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 listList 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 mergeMerge with the plot you're facing
/plot unmergeSplit this plot off the merge group
/plot helpShow command help

Permissions

World management

PermissionDescription
jexmultiverse.commandUse /multiverse (root)
jexmultiverse.command.createCreate worlds
jexmultiverse.command.deleteDelete worlds
jexmultiverse.command.editOpen the world editor GUI
jexmultiverse.command.teleportTeleport to managed worlds
jexmultiverse.command.loadLoad worlds from the database
jexmultiverse.command.listList managed worlds
jexmultiverse.command.applyschematicRetroactively paste a schematic into a world's plots
jexmultiverse.spawnUse /spawn

Plot management

PermissionDescription
jexplots.commandUse /plot (root)
jexplots.command.claimClaim plots
jexplots.command.unclaimUnclaim plots
jexplots.command.infoView plot info
jexplots.command.trust / .untrustManage trusted members
jexplots.command.deny / .undenyManage denied players
jexplots.command.homeTeleport to owned plots
jexplots.command.listList owned plots
jexplots.command.flagManage plot flags
jexplots.command.borderChange a plot's wall material
jexplots.command.merge / .unmergeMerge / unmerge plots
jexplots.command.menuOpen the plot menu GUI
jexplots.claim.<n>Allow up to n claimed plots (highest matching wins)
jexplots.claim.unlimitedNo claim cap
jexplots.merge.<n>Allow merged groups up to n plots
jexplots.merge.unlimitedNo merge cap
jexplots.bypass.protectStaff bypass - ignore protection on all plots

Plot system

JExMultiverse ships a self-contained plot system for PLOT-type worlds. No PlotSquared dependency.

Claiming

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.

Trusted / denied members

  • /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 info and 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.

Flags

Boolean overrides per plot. Default is the listed value when no override is set.

FlagDefaultWhat it does
pvpfalseWhen true, anyone can fight in this plot. When false (default), only owner ↔ trusted PvP is allowed.
mob-spawningtrueWhen false, hostile mobs (creepers, zombies, phantoms, slimes, ghasts, etc.) don't naturally spawn. Spawn eggs / spawners still work.
explosionfalseWhen false, blocks inside this plot survive creeper, TNT, wither, and end-crystal explosions. Other plots / terrain in the same blast still take damage.
fire-spreadfalseWhen false, fire won't spread or burn blocks. You can still light fires; they just don't propagate.
keep-inventoryfalseWhen true, players who die inside the plot keep their items + XP. Drops are cleared and dropped XP is zeroed.
entrytrueWhen 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-flowfalseWhen false, water and lava can't flow into the plot - useful for protected builds adjacent to fluids.
ice-form-meltfalseWhen 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).

Custom border

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

Merging

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

GUI menu

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

Schematics

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 a LimitedRegion). Use /mv applyschematic once chunks are loaded.
  • .nbt schematics paste during generation AND retroactively, no manual step needed.

Editions

CapabilityFreePremium
World limit3Unlimited
DEFAULT generator
VOID generator
PLOT generator
Plot ownership / flags / merging
Schematic import
World editor GUI
/spawn + global spawn
Developer API

Developer API

JExMultiverse registers MultiverseProvider with Bukkit's ServicesManager.

importde.jexcellence.multiverse.api.JExMultiverseAPI;
importde.jexcellence.multiverse.api.MultiverseProvider;
importde.jexcellence.multiverse.api.PlotCoord;
importde.jexcellence.multiverse.api.PlotBounds;
// Obtain the providerMultiverseProvidermv = JExMultiverseAPI.get();
// World snapshots - all return CompletableFuturemv.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 chainmv.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).booleanallowed = 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.

Building from Source

# 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:publishLocal

Artifacts:

  • jexmultiverse-free/build/libs/JExMultiverse-<version>-Free.jar
  • jexmultiverse-premium/build/libs/JExMultiverse-<version>-Premium.jar

Credits

  • 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)

About

JEMutliverse is a world handler, where you can create / edit worlds using custom generators like a custom Plot world (still in progress) or a void, default world.

Resources

Stars

11 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages