HomeJavaModsUltraRanks
UltraRanks
ModsJava

UltraRanks

Tags, rank shop, rankup and prestige in one plugin.

⬇ Download on Spigot
banner-a-minimal.png
UltraRanks
Cosmetic tags, a rank shop, a rankup ladder and prestige. One plugin, built on LuckPerms.

Most servers end up running three plugins for this: one for tags, one for rankup, one to sell ranks. They each keep their own data, they each have their own menu style, and none of them talk to each other.

UltraRanks does all of it, and keeps every bit of player data in LuckPerms rather than in a store of its own.

That last part is the whole idea. Your equipped tag is a LuckPerms prefix. An owned tag is a permission node. A rented rank is a temporary inheritance node with its own expiry. Prestige is a meta value. So:


To be straight about it: the plugin does have a storage section, and it does support MySQL. That is not for player data - it is for the handful of things that belong to the server rather than to one player: the leaderboard, running boosters, purchase cooldowns and the audit log. Those sit in flat files out of the box and you never have to touch them. Point them at a database only if you want them shared across a network. Details at the bottom.

The requirement engine

Every requirement in the plugin uses the same syntax, and it works in rankup.yml, ranks.yml, tags.yml and on prestige:

Code (YAML):
requirements :
 - "money:250000"                       # withdrawn on success
  - "playtime:20h"
  - "blocks:STONE:10000"                 # any block, or one specific block
  - "mobs:ZOMBIE:100"
  - "kills:25"                           # also deaths, level, exp, prestige
  - "statistic:FISH_CAUGHT:100"           # any Bukkit statistic
  - "statistic:USE_ITEM:BOW:500"
  - "permission:!blacklist.rankup"       # ! negates
  - "placeholder:%jobs_total_level%>=50" # any PlaceholderAPI value
That last line means any plugin with a placeholder can gate a rank. Jobs, quests, islands, playtime trackers, McMMO. No addon needed.

Rewards use the same idea:

Code (YAML):
rewards :
 - "money:15000"
  - "item:NETHERITE_INGOT:2"
  - "command:crate give %player% legendary 1"
  - "permission:ultraranks.tag.veteran"
  - "group:builder"
  - "title:&6RANK UP;&7You are now Veteran"
  - "broadcast:&e%player% reached Veteran"
  - "sound:ENTITY_PLAYER_LEVELUP:1:1.2"
divider-tags.png

What's in it

Tags
Paginated menu with categories and rarities. Tags set a prefix, a suffix or both. Unlock them with a permission, or put a price on them and let players buy them in game. Buyable tags can carry their own requirements, so a premium tag can still demand playtime instead of being pure pay to win. Tags can also be rented for a duration, same as ranks.

Rank shop
Rent ranks by duration or sell them permanently. Gifting, per offer sales, permission based discounts ( ultraranks.discount.25), purchase cooldowns and confirmation screens above a price you choose. Buying a rank you already rent extends the time you have left instead of overwriting it. Players get warned before a rental runs out, and you decide what happens when it does.

Rankup ladder
Unlimited rungs. /rankup max climbs as far as the player can afford in a single transaction: one balance check, one withdrawal, one permission write, rewards for every rung passed. The ladder menu shows live progress bars and a tick/cross checklist per requirement.

Auto rankup
A background check promotes players the moment they qualify. Players toggle it themselves with /autorankup. If you'd rather keep /rankup a deliberate action, set notify-only and it just nudges them on the action bar instead.

Prestige and seasons
At the top of the ladder players reset for a permanent prestige level, and every numeric requirement is multiplied after that, linear or compounding. /ultraranks season reset pays out the top players first, then puts everyone back at the start. Cosmetic tags are never touched by a reset.

Boosters
Server wide events. A weekend booster that halves rankup costs and takes 20% off the shop, or one you start by hand for an hour. A booster only discounts what a player actually pays: playtime and blocks are never scaled down, because a sale shouldn't cheapen effort somebody already put in.

Leaderboard
/rankup top and /prestige top, ranked by prestige then ladder position. Exposed as placeholders for holograms and scoreboards.

Bedrock support
If you run Geyser and Floodgate, Bedrock players get a native form instead of a chest menu. Chest GUIs misalign on Bedrock and phone players can't hover to read item lore at all, so the line that matters (price, LOCKED, CLICK TO BUY) is folded into the button label, and confirmations become a proper two button modal. Servers without Floodgate are unaffected.

Signs and vouchers
Put [UltraRanks] on a sign with rankup, tags, shop or top underneath. Vouchers are items that grant a tag or rank on right click, which is how you hand ranks out from crates and giveaways. What a voucher is worth lives in the item's persistent data, not its name, so renaming it in an anvil does nothing.

Audit log
Every purchase, rankup, prestige and refund is written down and readable with /ultraranks log. When somebody says the shop ate their coins, you have an answer.

Menus are data
Size, title, background, buttons, and what each button does all live in menus.yml. Buttons can be hidden behind a permission or behind any requirement string, so the menu reacts to the player. Gradients work everywhere: <gradient:#7B2FF7:#00D4FF>ASCENDANT</gradient>

divider-shop.png

Commands

Command What it does Permission
/tags [tag|category|off|list] Tag menu, or equip directly ultraranks.command.tags
/ranks [rank] Rank shop, or buy directly ultraranks.command.ranks
/ranks gift <player> <rank> Buy a rank for someone else ultraranks.command.ranks
/ranks stats Your progress and spending ultraranks.command.ranks
/rankup Advance one rank ultraranks.command.rankup
/rankup max Climb as far as you can afford ultraranks.command.rankup.max
/rankup menu The ladder screen ultraranks.command.rankup
/rankup top Leaderboard ultraranks.command.rankup
/prestige [info] Reset for a prestige level ultraranks.command.prestige
/autorankup [on|off] Toggle automatic promotion ultraranks.autorankup
/ultraranks help Help screen, filtered by permission none


Admin, all under ultraranks.admin:

Code (Text):
/ur reload                                 reload every config file
/ur info                                   plugin and hook status
/ur debug                                  full diagnostic dump
/ur log [player] [lines]                   transaction log
/ur tag give|take|set|clear <player> [tag]
/ur rank give|take <player> <rank> [duration]
/ur rankup <player> [steps]                negative steps rank down
/ur prestige set <player> <level>
/ur voucher tag|rank <id> [amount] [player]
/ur booster list|start <id> <time>|stop
/ur season info|reset confirm
/ur leaderboard [reset]
/ur storage [migrate <yaml|sql>]
Permissions

Node Default Notes
ultraranks.command.tags true
ultraranks.command.ranks true
ultraranks.command.rankup true
ultraranks.command.rankup.max true Chained rankups
ultraranks.command.prestige true
ultraranks.autorankup true Eligible for automatic promotion
ultraranks.admin op All admin commands, sign creation, update notices
ultraranks.tag.<id> false Owning a tag. ultraranks.tag.* grants all
ultraranks.discount.<percent> false e.g. ultraranks.discount.25 pays 75%. Highest wins, capped in config


Placeholders

Code (Text):
%ultraranks_tag%                  %ultraranks_tag_raw%         %ultraranks_tag_id%
%ultraranks_tag_name%             %ultraranks_suffix%
%ultraranks_tags_unlocked%        %ultraranks_tags_total%
%ultraranks_rank%                 %ultraranks_rank_group%      %ultraranks_rank_index%
%ultraranks_next_rank%            %ultraranks_next_rank_group%
%ultraranks_next_rank_cost%       %ultraranks_rankup_ready%
%ultraranks_rankup_progress%      %ultraranks_rankup_progress_bar%
%ultraranks_prestige%             %ultraranks_prestige_max%    %ultraranks_prestige_multiplier%
%ultraranks_ladder_size%          %ultraranks_ladder_position%
%ultraranks_discount%             %ultraranks_autorankup%
%ultraranks_position%             %ultraranks_leaderboard_size%
%ultraranks_top_1_name%           %ultraranks_top_1_rank%      %ultraranks_top_1_prestige%
%ultraranks_booster%              %ultraranks_booster_time%    %ultraranks_booster_discount%
%ultraranks_remaining_<offer>%    %ultraranks_owns_<offer>%
Requirements


Setup

  1. Drop the jar in plugins/ and start the server.
  2. Create the groups the default config references: /lp creategroup miner and so on. The console tells you exactly which ones are missing on startup, so you can't get this wrong quietly.
  3. Edit the configs and run /ur reload.

6 config files, split by what they do: config.yml, tags.yml, ranks.yml, rankup.yml, menus.yml and lang/.

14 languages ship with it, translated properly rather than run through a machine: English, Slovak, Czech, Polish, Russian, Ukrainian, German, French, Spanish, Portuguese, Italian, Dutch, Turkish and Simplified Chinese. Set general.language and you are done - or copy any file and write your own. Anything a translation misses falls back to English, so a half finished translation still works, and an update that adds messages never breaks the file you already translated.

Storage

On a single server you can skip this section entirely. It ships on flat files, works out of the box, and nothing here needs configuring.

Player data is in LuckPerms, as described at the top. What this section covers is the leftovers - the leaderboard, running boosters, purchase cooldowns and the audit log - because those belong to the server, not to one player, and LuckPerms has nowhere sensible to put them.

Flat files by default. If you run a network and want those shared, point storage.type at mysql, mariadb, sqlite or postgres. Connections come from HikariCP, and the MySQL driver is declared in plugin.yml so the server fetches it once by itself - there is no jar for you to hunt down.

Switching backends only redirects new data, so /ur storage migrate yaml copies across what you already have and leaves the source untouched. That means you can run it twice, or run it back the other way, without losing anything.

If the database is unreachable at startup the plugin falls back to flat files and says so in the console rather than refusing to load. Worth knowing: connectTimeout in storage.sql.properties is how long a dead database delays your startup before that fallback kicks in.

For developers

Code (Java):
RegisteredServiceProvider <UltraRanksAPI > rsp =
        Bukkit. getServicesManager ( ). getRegistration (UltraRanksAPI. class ) ;
UltraRanksAPI api = rsp. getProvider ( ) ;

api. setTag (player, api. getTag ( "ninja" ) ) ;
double percent = api. getRankupProgress (player ) ;
Cancellable events: PlayerTagChangeEvent, PlayerTagPurchaseEvent, PlayerRankPurchaseEvent, PlayerRankupEvent, PlayerPrestigeEvent. The purchase events let you rewrite the price, which is how you bolt on your own sale logic.

divider-prestige.png
Notes

Every LuckPerms write goes through modifyUser, which runs off the main thread. Economy checks and withdrawals run async too, so an SQL backed economy can't stall your tick. A per player lock covers the whole check, withdraw and permission write sequence, so spam clicking a menu can't pass one balance check twice. If a permission write fails after payment, the money goes back and the player is told.

This is free. If it saves you setting up three plugins, leave a review, that's payment enough. Bug reports and feature requests go in the discussion tab and I read all of them.

UltraRanks is a free Minecraft Java mod. Compatible with Minecraft 1.20, 1.20.6, 1.21, 26.1 and newer. Downloaded 4 times (via Spigot). Download it and open it directly in the game.

Explore more