Skip to content

Releases

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 04 Nov 16:59
c520f13

0.12.0 (2026-11-04)

⚠ BREAKING CHANGES

  • core: the regions module, /regions and its uxmessentials.regions.* nodes are removed. Region placeholders keep their regions_* names and are answered by guard; regions_available now says whether guard is on.

Features

  • command: refuse with the catalog line, never Brigadier's text (#65) (40d13cb)
  • config: apply command-control edits on reload (#56) (b180d89)
  • config: cover a whole plugin with one command-control entry (#58) (4a15105)
  • config: read command-control entries down to their arguments (#57) (a49ccea)
  • core: add the guard module and remove regions (#62) (98d7f41)
  • core: hold the server's operators to an allowed list (#59) (b90a389)

Bug Fixes

  • command: let command words use the letters of every language (#60) (57cb020)
  • integration: import a passthrough deny global region as protected (#63) (dda7687)
  • menu: write the example menu title without colour (#55) (18cb506)
  • message: describe /setspawn as the current world's spawn (#61) (3eb993c)
  • message: say how long a kit cooldown has left (#64) (b745bf0)
  • message: write the Latin-script languages in small capitals (#53) (7b9219a)

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 01 Nov 22:24
b20765b

Added

  • Correct and import playtime.
  • Show each language's readers their own command words.
  • Answer the shared leaderboard placeholders.
  • Rank money earned and spent.
  • Rank playtime, trades and prestige.
  • Rank votes on the shared boards.
  • Step back from chat features uxmChat runs.

Changed

  • The warp picker's effect and sound presets are named in every language's messages file.
  • The network block names this backend with server-name; a file that still says server-id keeps working.
  • The shipped config.conf lists storage right after language, and menu last.
  • The SQLite database lives under data/ and moves there by itself on the first start. The config copy is in backups/.

Fixed

  • Point the plugin website at its uxplima.com product page.
  • Join hologram redraws and parse shared words once.
  • Send nametags only to clients that track the wearer.
  • Mark vanished players for other plugins.
  • Put navigation where the conventions say.
  • Describe the new playtime subcommands in help.

v0.10.3

Choose a tag to compare

@github-actions github-actions released this 28 Oct 06:56
3ea0c4f

0.10.3 (2026-10-28)

Fixed

  • An amount with a leading zero, such as 0.500 or 0.001, is read as a decimal. Before this, /pay 0.500 paid 500.
  • The permission list describes the kit cooldown and home permissions the way the plugin checks them.

v0.10.2

Choose a tag to compare

@github-actions github-actions released this 27 Oct 19:58
bf328e6

0.10.2 (2026-10-27)

Added

  • The bossbar module: bars that stay up, timed bars and announced bars. Bars reach placeholders, the API and REST, a rotating frame is read in each player's language, and a visibility event is published.
  • The pause-menu link labels are read in each player's language, and the links are sent again when a player chooses another language.

Changed

  • Every skin name opens unless the operator restricts it, and the console can dress another player.
  • Menus play the sounds config.conf names, and every shipped window is filled with the house filler.
  • Releases are tagged vX.Y.Z again, and the jars and a SHA256SUMS file are attached to every release. Commands, permissions, configuration files and stored data stay as they were.

Fixed

  • The worlds module reaches every dimension of Paper 26.2. A world can be named by its key (minecraft:the_nether, mypack:mining), by the bare path of the nether or end (the_nether), or by the name the server gives it (world_nether, mypack_mining). A datapack dimension is found under its own namespace and loads from there on every start.
  • /worlds import reads the environment from the dimension when none is given, instead of answering "Unknown or incomplete command".
  • A player's HUD keeps drawing after the server drops one of their renders.

v0.10.1

Choose a tag to compare

@siracozmen01 siracozmen01 released this 25 Oct 18:19

Upgrading from 0.10.0

Replace the jar and restart. Nothing has to be edited by hand.

  • Your data stays where it is. The database keeps its tables under their current names, and the migrations that were already applied are recognised and not run again.
  • Your files are kept. A setting or a message line you changed is not touched. New settings and new message lines are added to your files. A message line you never changed is brought to its new wording.
  • The storage block has new names, type and pool-size, shared with the rest of the plugin family. A file that still writes backend and read-pool-size keeps working as it is.
  • A storage word that names no database stops a new install, so a network server cannot quietly start on a file of its own. A server that already runs on its SQLite file under such a word keeps doing so and says it in the console.
  • No command, permission node or public API was removed or renamed.

Fixed

  • /lay, /bellyflop and /spin could leave a player invisible for good: after a pose started in spectator mode or under an invisibility potion, and after a reload or a restart during a pose. A pose now gives the body back on every exit, and after a crash on the next join.
  • /poses reveal <player> (uxmessentials.poses.reveal, operators by default, the console too) gives back a body an older version left invisible.
  • A player's name is filled into an operator's command, click action, kit action, vote reward, NPC command and placeholder currency only when an account could have that name. A server that turns off Paper's name check can let in a name with a space or a bracket, which would add an argument to a command or change a message. Such a line is now skipped and the console says so.
  • A chat message keeps the colour another plugin put on it.
  • A world's day and weather cycles are left alone when nothing locks them.
  • Floodgate is found even though it enables after this plugin.

New

  • storage.table-prefix for a new install, storage.local-only for the one server of a network that keeps its own rows, and storage.copy-from-file to move a SQLite file into a network database on the first start.
  • Holograms are drawn for each viewer with packets, in their own language, and redrawn on /uxmess reload. A click reaches a hologram from 12 blocks by default.
  • Nametags, tab names and chat prefixes are drawn for each reader, with relational placeholders and ranks written as catalogue lines in the reader's language.
  • An NPC turns back to its placed facing when its viewer walks away.
  • %uxmessentials_player_language%, the language a player reads in.
  • A chat line that opens with <center> is centred, and an announcement can set centered = true.
  • /uxmess reload reads the custom menus again.
  • Admin commands answer in the operator's own language.

Faster

  • The scoreboard and the tab list spread their work over the refresh interval and parse each line once.
  • An NPC turns in one packet per viewer, and only when its look changes.
  • PlaceholderAPI is asked only about text that holds a placeholder.

0.10.1-dev.1 (development build)

Pre-release

Choose a tag to compare

@siracozmen01 siracozmen01 released this 18 Oct 09:42

A development build for testing, not a release. It is not published to Modrinth or Hangar.

Fixes the global refresh-ticks of the scoreboard and tablist being ignored in the single-board shape (#3).

v0.10.0

Choose a tag to compare

@siracozmen01 siracozmen01 released this 13 Oct 07:32

uxmEssentials 0.10.0

A server can now keep its players in its own language, and a staff member can set another player's language.

Requires Paper 26.2 on Java 25, same as 0.9.0.

Read this before you update

messages.default-locale becomes the language block. config.conf now carries this block, the same one every UXPLIMA plugin reads:

language {
  default = "en"
  follow-client = true
  force = ""
}

Your old messages.default-locale keeps working. When the update appends the block to your file, your old value still wins over the shipped "en". If you write a default in the new block and it differs from the old line, the console warns you: remove the old line then.

A player's choice moves. /lang now keeps the choice on the player's own data under uxmlib:language. A choice saved under the old key is moved the first time the player is seen. Nobody has to choose again.

Languages (#2)

A server can keep its own language. Before, a player whose client read English read English, even on a server whose default was German. Now:

  • default is what a player reads when nothing else answers.
  • follow-client = false starts every player in the default. They may still choose another with /lang.
  • force = "de" puts everybody in one language, whatever they chose. /lang then says so instead of changing anything.

One choice for every plugin of ours. A language chosen with /lang is read by every UXPLIMA plugin on the server, and a choice made in any of them is read here. uxmLang is not needed for this. With uxmLang installed, the choice also follows the player between servers.

Set another player's language.

  • /lang set <player> <language>
  • /lang reset <player>

Both work for a player who is offline: the choice is kept and applied when they next join. Both need uxmessentials.lang.others.

Every new line is in all twelve catalogues.

Under the hood

  • On uxmLib 0.163.0.
  • The order a language is picked in lived in four places and now lives in one.

v0.9.0

Choose a tag to compare

@siracozmen01 siracozmen01 released this 01 Oct 19:25

uxmEssentials 0.9.0

A large release: the plugin starts on MySQL, MariaDB and PostgreSQL again, every menu now runs on the uxmLib menu engine with native Bedrock forms, the colours come from a theme file, and window titles keep the MiniMessage you write in them.

Requires Paper 26.2 on Java 25, same as 0.8.2.

Read this before you update

Discord account linking is gone. /link and the linked-account tables are removed. The V85 migration drops both tables and the rows in them. The Discord bridge itself stays: chat, the audit channel and the rest work as before.

Old message files and window titles. The vault, shulker box and disposal titles now ship without a colour tag. A messages file extracted by an older version keeps its <title> tag, and since titles are no longer flattened, that tag now colours them. Delete the tag from those lines if you want them plain.

New settings are added to your files, not over them. A setting this release adds is appended to the end of your existing config.conf and module files as a commented block. Nothing you wrote is overwritten.

Fixes

MySQL, MariaDB and PostgreSQL start again. Three migrations could not run on a network database: a comment MySQL does not accept, a column named with a reserved word, and a column type PostgreSQL does not have. Every migration now runs on all three, and a first start on MariaDB no longer prints a wall of "ignored for PRIMARY key" warnings.

Window titles keep their MiniMessage (#1). Every title used to be flattened to plain text, so a <lang:...> key showed as its raw name and a <font:...> was dropped. Titles are now drawn as written.

Titles drawn with a resource pack line up. A title containing a translated key, a pack font or a keybind is never padded, because its width cannot be measured. A server that wants every window title on the left writes this in plugins/uxmTheme/theme.conf (shared by all our plugins) or plugins/uxmEssentials/theme.conf:

menu-titles = left

Chat and moderation

  • A muted player is kept out of public chat.
  • A sanction with no end reads as permanent, in the reader's language.
  • A long issuer name is cut to fit its column rather than losing the sanction.

Commands

  • A bare command answers the console, and every usage line is built from the catalogue, with optional branches bracketed whole.
  • /mail send, /unignore and the ignore window reach a player who is offline.
  • Playtime is read for a player who has logged off, and the leaderboard prints to the console.
  • /bottom stands you in open space, and /up gives you a floor.
  • /lang offers every language that has a catalogue.
  • /clearchat tells the console it ran.
  • The join message no longer suggests a /sethome that is not registered.
  • A custom command names the player it could not find.
  • Every command is described in the reader's language, in all twelve catalogues.

Economy and selling

  • The native ledger is published as a Vault economy, and Vault is bound once the server has loaded.
  • A sale takes the items before it pays for them, and sells only plain stacks.
  • The wallet events fire on every change of money.

Worlds

  • World files are found where Paper 26.2 keeps them, and our generators are served to the default world.

REST API

  • A missing resource answers 404 not-found with a plain reason.
  • A negative amount is refused as a bad request.
  • A sanction with a field the route does not read is refused.
  • An event about an offline player is still delivered.

Menus

Every menu now renders through the uxmLib menu engine. A Bedrock player gets a native Floodgate form for every window. A layout with fewer slots than things to draw is reported to the operator rather than cutting the list short quietly, and a broken placeholder costs its own token rather than the whole window.

Theme

The colours, the title glyph and the window title alignment come from a theme file. plugins/uxmTheme/theme.conf is shared by every UXPLIMA plugin on the server, and plugins/uxmEssentials/theme.conf overrides it for this plugin alone. /uxmess reload reads it again.

Diagnostics

/uxmess doctor reports the schema version the database is really on.

v0.8.2

Choose a tag to compare

@siracozmen01 siracozmen01 released this 28 Aug 10:24

uxmEssentials 0.8.2

A bug-fix release for two faults in 0.8.1 that could stop a server dead, plus the new Custom Commands module and a per-world void rescue.

Requires Paper 26.2 on Java 25, same as 0.8.1.

Fixes

The PIN keypad no longer fights itself. On a server that requires a PIN, the create-a-PIN pad looped: the first entry went in fine, then the moment the pad asked for the PIN a second time it tore itself down and rebuilt faster than anyone could tap it, and the entered digits were wiped on every rebuild. Setting a PIN was impossible, and since the player is frozen until they have one, so was joining.

Two things were wrong. Showing a window over an open one makes the server close the open one first, so every pad the plugin put up while another was on screen arrived as a keypad close, and the listener that guards against a frozen player escaping read that as an escape and reopened. The guard meant to prevent exactly this was released before the open it guarded had actually landed, because opening a menu is asynchronous. The plugin now counts the opens it has asked for and not yet seen appear, so a close caused by its own open is told apart from a player walking away. The enrolment flow also no longer puts up a second pad at all: the submit button already clears the entry and redraws in place, so both entries happen at one window. A frozen player who closes the keypad still gets it straight back, exactly once.

A custom command no longer stops the plugin from enabling. A definition in commands/custom/ is keyed in the command catalog under a namespace, custom:<id>, and the catalog's identifier type refused the colon, so a single definition file was enough to fail onEnable outright. Namespaced identifiers are accepted now, and the generated commands.conf quotes such a key, since HOCON would otherwise read the colon as the separator between a key and its value.

Custom Commands

The 36th module, and a replacement for MyCommand. An operator declares a command in a file under commands/custom/ and the plugin registers it as a real command: typed arguments with tab completion, a usage line, and a place in commands.conf beside the built-in ones.

command {
  name = "welcome"
  aliases = ["hello"]
  permission = "uxmessentials.customcommand.welcome"
  console = true
  cooldown = "5s"
  cost = 0
}

arguments = [
  { name = "target", type = online-player }
]

actions = [
  "message:<green>Welcome sent."
  "delay:1s"
  "broadcast:<gold>%player% <yellow>welcomes <gold>%arg_target%"
]
  • The actions are the menu engine's own. Everything a menu button can do, a custom command can do, plus delay:<duration> between steps. Nothing new to learn if you have written a menu.
  • Real arguments. string, rest, int, double, bool, material, world, online-player, player, with min and max on the numeric ones, so an out-of-range value is a syntax error before a single action runs. %arg_<name>% and %args% expand inside the actions.
  • Real gates, in a fixed order: sender kind, permission, chain depth, requirements, cooldown, warmup, cost. The cost is charged after the warmup completes, so a warmup a player walks out of costs nothing.
  • A one-line alias instead of an action list: alias = "/gamemode creative" passes everything typed after your command straight through.
  • Written in game if you prefer. /customcmd create <id> asks for the command word, the aliases, the permission, then each argument and each action, and shows you the finished file before it writes anything. /customcmd list, info, test, reload, run and delete cover the rest.
  • Privileged steps are opt-in and audited. console: and command-as-op: are gated in the module's config, and a chain using a disabled one skips that step and says so rather than failing silently.

A bad definition never takes the others down: a file that fails to parse is skipped with a console warning naming it, and everything else still loads.

Worlds: void rescue

A player who falls out of a world no longer falls forever. Each world can name an ordered rescue chain (spawn, warp:<name>, at <world> <x> <y> <z>) and the height below which it fires, and the first step that resolves wins. It uses the involuntary-move path, so it leaves no /back point and plays no arrival effects.

Also

  • The shipped teleport config now documents the spawn { first-join / every-join / respawn / respawn-chain / exempt-permission } block that 0.8.1 introduced.
  • The build follows uxmLib to its renamed repository and its 0.5.0 line.

Downloads

File Where it goes
uxmEssentials-0.8.2.jar Paper plugins/ (required)
uxmEssentials-velocity-0.8.2.jar Velocity plugins/
uxmEssentials-redis-0.8.2.jar Paper plugins/ on each backend
uxmEssentials-discord-0.8.2.jar Paper plugins/
uxmEssentials-rest-0.8.2.jar Paper plugins/

Upgrading from 0.8.1 is a drop-in: settings new in this version are appended to your existing config files under a header naming the version, and nothing you have edited is touched.

v0.8.1

Choose a tag to compare

@siracozmen01 siracozmen01 released this 27 Aug 15:37

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-empty are 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 with number-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 exact mode. With exact = true all 80 cells are materialized, including the ones you did not author, so a filler grid stays a grid. It requires suppress-real-players = true and 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, /ping and 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 /back point, 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-nether or allow-end is 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-join is on. A genuinely new player is placed at the resolved spawn. If you already handle first join with another plugin, set it to false.
  • spawn.respawn is on, with the chain bed, anchor, spawn. A valid bed or respawn anchor is still preserved; what changes is that a player without one lands on your /setspawn instead of the vanilla world spawn. Set spawn.respawn = false for the old opt-in behaviour, or give a world an empty respawn.chain.<world> list to leave that one world vanilla.