Hierarchy
Permissions, chat and tab list in one plugin — for Bukkit, Spigot, Paper and BungeeCord, from Minecraft 1.19 up to the current release.
Hierarchy manages ranks with weights and inheritance, writes prefixes and suffixes into the chat and the player list, and stores everything either in plain YAML files or in a shared MySQL database. Every message exists in English and German.
- One jar for all platforms — the same file works as a server plugin and as a BungeeCord plugin
- Wildcards (
essentials.*), negated nodes (-worldedit.command), per-world and per-server scopes, temporary ranks and temporary permissions - Chat format and tab list format per group, animated tab header and footer
- Tab list sorted by rank weight
- YAML or MySQL, with live synchronisation between servers and a one-command migration between both
- Vault permission and chat provider, optional PlaceholderAPI support
- No external services, no telemetry
Install
Server (Bukkit, Spigot, Paper)
- Drop
hierarchy.jarintoplugins/. - Start the server.
config.yml,groups.ymlandlang/are created inplugins/Hierarchy/. - Give your staff
hierarchy.admin, for example with/hr user group set <name> admin.
Proxy (BungeeCord, Waterfall)
- Drop the same
hierarchy.jarinto the proxyplugins/folder. - Start the proxy. Its own
plugins/Hierarchy/folder is created. - Point both the proxy and all backend servers at the same MySQL database so ranks are shared (see Storage).
Requirements: Java 17 or newer, Minecraft 1.19 or newer. MySQL is optional; the
driver is downloaded by the server on first start and only used when
storage.type is set to mysql.
First steps
groups.yml ships with a working ladder:
| Group | Weight | Inherits | Prefix |
|---|---|---|---|
default |
0 | — | &7 |
vip |
100 | default |
&a[VIP] &a |
moderator |
500 | vip |
&9[Mod] &9 |
admin |
1000 | moderator |
&c[Admin] &c |
Everybody who is not in any group is treated as a member of the group marked
default: true.
/hr group create builder 250
/hr group set builder prefix &b[Builder] &b
/hr group parent add builder default
/hr group permission add builder worldedit.*
/hr user group set Notch builder
Commands
/hierarchy with the aliases /hr, /perm and /rank.
| Command | Effect |
|---|---|
/hr help |
Command list |
/hr info |
Platform, storage, group and player count, language |
/hr reload |
Reload config.yml, groups and language files |
/hr group list |
All groups, highest weight first |
/hr group info <group> |
Everything about one group |
/hr group create <group> [weight] |
Create a group |
/hr group delete <group> |
Delete a group and remove it from all members |
/hr group set <group> <property> <value> |
Change a group, see below |
/hr group parent <add|remove> <group> <parent> |
Change inheritance |
/hr group permission <add|remove> <group> <node> [flags] |
Change permissions |
/hr user info <player> |
Groups, prefix, permissions, expiry times |
/hr user group <set|add|remove> <player> <group> [duration] |
Change membership |
/hr user permission <add|remove> <player> <node> [flags] |
Player specific permissions |
/hr user set <player> <prefix|suffix> <value> |
Override prefix or suffix for one player |
/hr check <player> <node> |
Shows whether a node is granted, denied or unset |
/hr migrate <yaml|mysql> |
Copy everything into the other storage |
Players do not have to be online. Offline players are looked up in the storage and in the server's player cache.
Properties for /hr group set
| Property | Meaning |
|---|---|
prefix, suffix |
Text in front of and behind the name |
display |
Readable group name, used by %group_display% |
weight |
Rank order; higher wins and sorts further up in the tab list |
chat |
Chat format for this group, empty falls back to chat.format |
tab |
Tab list format for this group, empty falls back to tab.name-format |
default |
true makes this the group for everyone without a rank |
Use - or none as the value to clear a property.
Flags for permission commands
| Flag | Example | Meaning |
|---|---|---|
world= |
world=creative |
Node only applies in that world |
server= |
server=lobby |
Node only applies on that server name |
true / false |
false |
Grant or deny; false is the same as writing -node |
| duration | 30d, 12h, 90m, permanent |
Node expires automatically |
Durations accept s, m, h, d, w and y and can be combined: 1d12h.
A plain number means minutes.
/hr group permission add vip essentials.fly world=creative
/hr group permission add vip -essentials.tpa
/hr user permission add Notch worldedit.* 7d
/hr user group add Notch vip 30d
How permissions are resolved
- All non-expired group memberships are collected; without any membership the default group is used.
- Inherited groups are applied first, then the group itself, groups with a higher weight after those with a lower one.
- The player's own nodes are applied last and always win.
- A check first looks for the exact node, then for
a.b.*,a.*and finally*. - If nothing matches, the decision is left to the server, so
plugin.ymldefaults and operator status still work.
Negated nodes (-node or false) are real denials. They beat a wildcard from a
lower priority, which is how you take single commands away from an inherited
rank.
Chat
chat:
enabled: true
format: '%prefix%%player%%suffix% &8» &f%message%'
per-world: false
color-permission: hierarchy.chat.color
placeholderapi: true
log-to-console: true
A group with a chat-format of its own overrides chat.format. Players with
hierarchy.chat.color may use colour codes in their messages; for everyone else
the codes are removed. With per-world: true a message only reaches players in
the same world.
Hierarchy cancels the original chat event and sends the formatted line itself.
On Paper the component chat event is used, on Spigot and Bukkit the classic one.
Plugins that only listen for chat to display it will therefore not see the
message a second time — chat loggers that read at MONITOR priority still do.
Tab list
tab:
enabled: true
name-format: '%prefix%%player%'
sort-by-weight: true
update-ticks: 40
animation-ticks: 20
header:
- '&b&lSERVER'
- '&3&lSERVER'
footer:
- '&7Online &f%online%&7/&f%max% &7Ping &f%ping%ms'
Several header or footer lines are played one after another, one frame every
animation-ticks. update-ticks controls how often names, ping and online
numbers are refreshed.
Sorting uses teams on the server's main scoreboard, named after the group
weight. Every team Hierarchy creates starts with hy and is removed again when
the plugin stops.
On a proxy only header and footer are applied — names in the player list belong to the backend server.
Placeholders
| Placeholder | Value |
|---|---|
%player% |
Name |
%displayname% |
Display name as other plugins set it |
%prefix%, %suffix% |
From the player override, otherwise from the highest group |
%group% |
Primary group |
%group_display% |
display-name of the primary group |
%weight% |
Weight of the primary group |
%world%, %server% |
World name, server name from config.yml |
%ping%, %online%, %max%, %tps% |
Live server values |
%message% |
Chat message, only in chat.format |
Colours: &a style codes everywhere plus hex as &#ff8800 or <#ff8800>.
With PlaceholderAPI installed, its placeholders work in every format too.
Storage
storage:
type: yaml
mysql:
host: localhost
port: 3306
database: minecraft
username: root
password: ''
table-prefix: hierarchy_
use-ssl: false
pool-size: 6
sync-seconds: 15
jdbc-url: ''
yaml keeps groups.yml and users.yml next to config.yml. Good for a
single server.
mysql keeps six tables (hierarchy_groups, hierarchy_group_permissions,
hierarchy_users, hierarchy_user_groups, hierarchy_user_permissions,
hierarchy_meta) and is the right choice for networks and for large player
counts. Tables are created automatically. MariaDB works as well; jdbc-url
replaces host, port, database and SSL settings when you need a custom one.
Every write raises a revision counter. All other servers notice it within
sync-seconds and reload groups and online players, so a rank given on one
server is live everywhere. 0 turns the check off.
If the database cannot be reached at start, Hierarchy logs the reason and falls back to YAML instead of leaving the server without permissions.
/hr migrate mysql copies all groups and players into the database,
/hr migrate yaml the other way around. Afterwards set storage.type and run
/hr reload.
Networks
Give every server a name:
server: lobby
That name is what server= scopes are matched against, so one database can hold
essentials.fly#creative for one server and nothing for the others. The proxy
handles permissions for proxy commands and the tab header; chat and the player
list are formatted by the backend servers.
Permission nodes
| Node | Default | Meaning |
|---|---|---|
hierarchy.admin |
op | All commands |
hierarchy.command.help |
everyone | /hr help |
hierarchy.command.info |
op | /hr info |
hierarchy.command.reload |
op | /hr reload |
hierarchy.command.group |
op | All /hr group commands |
hierarchy.command.user |
op | All /hr user commands |
hierarchy.command.check |
op | /hr check |
hierarchy.command.migrate |
op | /hr migrate |
hierarchy.chat.color |
no | Colour codes in chat messages |
Vault
With Vault installed, Hierarchy registers both the permission and the chat
provider, so plugins that ask Vault for groups, prefixes or suffixes get the
right answers. Nothing to configure; vault: false in config.yml turns the
registration off.
Language
language: en or language: de in config.yml. Both files live in
plugins/Hierarchy/lang/ and can be edited; new keys from an update are filled
in from the bundled English file. A third language is just another file, for
example lang/fr.yml with language: fr.
Other settings
permissions:
inject: true
default-group: default
display-name:
enabled: true
format: '%prefix%%player%%suffix%'
join-quit:
enabled: false
join: '&8[&a+&8] %prefix%%player%'
quit: '&8[&c-&8] %prefix%%player%'
permissions.inject replaces the permission handler of every player so that
wildcards and denials work for all plugins, not only for Hierarchy's own
commands. It is the recommended setting; if a server version does not allow it,
Hierarchy says so in the log and falls back to permission attachments, which
expand wildcards only against nodes that plugins have registered.
display-name writes prefix and suffix into the name used by /list and by
other plugins. join-quit replaces the vanilla join and quit messages; an empty
format hides them.
Developer API
import org.hierarchy.api.HierarchyApi;
import org.hierarchy.api.HierarchyProvider;
if (HierarchyProvider.available()) {
HierarchyApi hierarchy = HierarchyProvider.get();
String group = hierarchy.primaryGroup(player.getUniqueId());
String prefix = hierarchy.prefix(player.getUniqueId());
hierarchy.addGroup(player.getUniqueId(), "vip", System.currentTimeMillis() + 86_400_000L);
}
The interface also offers check, suffix, weight, groupsOf, groups,
removeGroup, setPermission, unsetPermission and reload. Write access
saves to the storage in the background and refreshes chat, tab list and
permissions of the player right away.
Build from source
./gradlew :hierarchy:build
The jar and a sources jar end up in hierarchy/build/libs. Compiled against
Spigot API 1.19.4, BungeeCord API and Java 17, so the same build runs on every
supported platform and version.
Information
Pinned Versions
- R1.19–26.3
Pages
Members
1Owner