Redis transport for the uxmEssentials cross-server bus, no proxy needed. Requires the main jar.
uxmEssentials 0.8.1
A maintenance release that finishes several surfaces 0.8.0 left half-built: the sidebar and tab list are rebuilt around per-viewer lines, /uxmess reload no longer runs on the tick thread, almost every administration command now works from the console, the doctor can repair what it finds, and spawn placement on join and on death is configurable in one block.
Requires Paper 26.2 on Java 25, same as 0.8.0.
The sidebar and tab list, rebuilt
The scoreboard renderer was rewritten around one idea: a line belongs to a viewer, not to the board.
- Write more lines than fit. Up to 128 candidate lines may be authored. Conditions and
hide-when-emptyare evaluated per player, and the first 15 that survive are what that player sees. A line that disappears no longer shifts the ones below it into the wrong identity. - Typed lines. A line can now be an object with a stable
id, so the renderer updates or moves that exact row instead of tearing down the rows around it. Plain strings still work and get an automatic id. - Right-aligned values.
"<gray>Balance||<gold>{coins}"renders the right side through animations, built-in tokens, PlaceholderAPI and MiniMessage, and sends it as that row's fixed number format. Typed lines can say the same thing withnumber-format = { type = "fixed", text = "..." }. - It yields. When another plugin displays its own sidebar objective, uxmEssentials steps aside; when that objective is cleared, its frame comes back. No more two plugins fighting over one slot.
- Tab list
exactmode. Withexact = trueall 80 cells are materialized, including the ones you did not author, so a filler grid stays a grid. It requiressuppress-real-players = trueand refuses to enable itself otherwise, because a native roster and a full synthetic grid cannot both decide the shape.
/uxmess reload behaves like an operator tool
- It reads and validates files off the tick thread, so a reload no longer stalls the server while it parses.
/uxmess reload <module>takes a module name with completion, instead of reloading everything.- A second reload while one is running is refused rather than queued.
- Each step that fails keeps its last known good values, and the report says which ones failed and how long the run took.
- Changes that are structural (a module turned on or off) are reported as needing a restart instead of half-applied to a running wiring.
Administration from the console
Roughly a hundred command classes were reworked so that a server owner without a player body can still run them. Anything that used to answer "players only" now either takes an explicit target or an explicit place:
- Placement commands take coordinates:
/setjail <name> at <world> <x> <y> <z> [yaw] [pitch], and the same shape for spawns, warps, worlds, holograms and NPCs. - Player-affecting commands take the player:
/heal,/feed,/god,/fly,/speed,/burn,/ice,/air,/clearinventory,/experience,/gamemode,/kit,/playtime,/pingand the rest. - The console is a real audience now: messages addressed to the actor reach it, and actions it takes are attributed to the console rather than to nobody.
Economy, holograms, NPCs, worlds, regions, kits, warps, player warps, jails and the item utilities are all covered.
The doctor can repair
/uxmess doctor gained a relational integrity probe over the whole database, and a repair for what it finds. /uxmess doctor repair is a preview that changes nothing; /uxmess doctor repair confirm is the one that writes, behind its own uxmessentials.admin.doctor.repair node.
Several child tables carry no database foreign key on purpose, because the same migrations have to run on SQLite, MySQL/MariaDB and PostgreSQL. Repositories delete children transactionally, but an interrupted import or a hand-edited database can still leave ownerless rows behind. The check finds them without loading a single domain object. The repair deletes only unambiguous orphans and clears nullable links whose target is gone; it runs in a transaction and rolls back on failure. Parent records are never deleted: a reference to a missing world may become valid again once that world is restored, so the doctor reports it and keeps it.
Spawn on join and on death, in one block
Join placement and respawn placement used to be two unrelated toggles in two places. They are now one policy, and both share the exact chain /spawn walks: a mirror redirect, then the world's own /setspawn, then the main spawn, then the vanilla world spawn.
spawn {
first-join = true
every-join = false
respawn = true
respawn-chain = ["bed", "anchor", "spawn"]
exempt-permission = "uxmessentials.spawn.join.exempt"
}
- One listener owns every automatic join move, so two independently configured handlers can no longer race each other. First-join RTP still wins when it is on.
- Automatic moves are involuntary: they do not write a
/backpoint, and they play no arrival title, sound or effect. Logging in should not overwrite the last place you chose to be. respawn.chain.<world>still works and still wins for that world; an explicitly empty list opts a world back into vanilla respawning.- The
warp:<name>step resolves from the warps module's warmed snapshot, and the spawn directory is cached, so a death never waits on the database. - A permission exempts a player from automatic join movement entirely.
One commands.conf, and aliases per language
The command catalog moves from commands/commands.conf to commands.conf at the root of the data folder. If your install has the old single file, it is moved on first load. An install that deliberately split the catalog across several files keeps working as a deprecated fallback, because losing an operator's edits to force a layout is not a trade worth making.
Commands can also carry aliases that only exist for a given language:
commands {
home {
localized-aliases {
tr = ["ev"]
de = ["zuhause"]
}
}
}
Every alias is registered globally, so dispatch, console use and Geyser translation stay ordinary Brigadier paths. What changes is visibility: when Paper builds a player's command list, aliases belonging only to other languages are hidden from it. Canonical names and ordinary aliases are never hidden.
Fixes
- PIN enrolment could be escaped. The keypad close listener only recognised the verification keypad, not the one used to create a PIN. Both are covered now.
- PIN length refusals said nothing useful. "Too short" and "too long" now render the actual minimum and maximum from your policy.
- A managed portal link could bypass the server's own policy. A nether or end portal is now cancelled when
allow-netherorallow-endis off, before any configured link is resolved.
Upgrading
Drop the new jars in and restart. Configs, permission grants and menus are untouched, and commands/commands.conf moves itself.
Two defaults are worth a look before you restart a live server:
spawn.first-joinis on. A genuinely new player is placed at the resolved spawn. If you already handle first join with another plugin, set it tofalse.spawn.respawnis on, with the chainbed, anchor, spawn. A valid bed or respawn anchor is still preserved; what changes is that a player without one lands on your/setspawninstead of the vanilla world spawn. Setspawn.respawn = falsefor the old opt-in behaviour, or give a world an emptyrespawn.chain.<world>list to leave that one world vanilla.