Permissions#
VSU gates every command through one class, PermissionGate. The gate composes
two sources of authority: a LuckPerms node grant and the vanilla operator level.
Either one alone is sufficient, and console always passes.
That union rule is the single most important thing to understand about VSU
permissions. It is why an unconfigured LuckPerms install does not lock players
out, and why an operator keeps working the moment they are opped even if no
vsu.* node has ever been granted.
The gate#
public static boolean check(CommandSourceStack source, String node, int opFallback) {
if (!source.isPlayer()) return true; // console, command blocks, functions
if (LuckPermsBridge.isPresent()
&& LuckPermsBridge.hasPermission(source.getPlayer().getUUID(), node)) {
return true; // LuckPerms grant
}
return source.hasPermission(opFallback); // vanilla op level
}
Three consequences follow directly:
- Console passes unconditionally. Server console, command blocks, and datapack functions are never filtered. Do not treat permission nodes as a security boundary against command blocks.
- LuckPerms is consulted first, but a denial there is not final. If LP is present and does not grant the node, the operator-level check still runs.
- Operator level is a floor, not a ceiling. The only way to remove an operator's access to a command is to de-op them.
LuckPerms is detected once, at class load, by probing for
net.luckperms.api.LuckPermsProvider. If the probe fails the log records
LuckPerms not detected on classpath; using vanilla op fallback and every check
falls through to the operator level. No command is disabled by its absence.
Node naming#
vsu.<category>.<subject>[.<scope>]
| Category | Meaning | Examples |
|---|---|---|
| Command namespace | Commands any player may run, usually on themselves | vsu.command.home, vsu.command.tpa, vsu.command.kit |
| Admin namespace | Staff utilities and world control | vsu.admin.heal, vsu.admin.peek, vsu.admin.world |
| Moderation namespace | Moderation actions | vsu.mod.ban, vsu.mod.mute |
| Bypass namespace | Opt-in exemptions from a restriction | vsu.bypass.mute, vsu.bypass.ban |
Full node table#
These 32 nodes are the complete tree for 2.2.0. Any vsu.* string not in this
table is not a VSU node.
vsu.bypass.ban is the one node not referenced from the common module: the join
listeners in the Fabric and NeoForge source sets check it directly, so it is
enforced by the jar even though no common-module command names it.
| Node | Op fallback | Used by |
|---|---|---|
vsu.admin.broadcast |
2 | /broadcast, /bc, /gc |
vsu.admin.crate |
2 | /crate administration subcommands |
vsu.admin.fly |
2 | /fly |
vsu.admin.gamemode |
2 | /gm |
vsu.admin.god |
2 | /god |
vsu.admin.heal |
2 | /heal, /feed |
vsu.admin.lag |
2 | /lag |
vsu.admin.manage |
3 | /vonixsu, /kit reload |
vsu.admin.peek |
2 | /invsee, /backsee, /accsee, /enderchest, /whois |
vsu.admin.setspawn |
2 | /setspawn |
vsu.admin.smite |
2 | /smite, /lightning |
vsu.admin.teleport |
2 | /tp, /tphere, /tpall, /tppos |
vsu.admin.vanish |
2 | /vanish |
vsu.admin.warp |
3 | /setwarp, /delwarp |
vsu.admin.world |
2 | /weather, /time, /day, /night, /sun, /rain, /storm |
vsu.bypass.ban |
— | Exempts the holder from the join-time ban check |
vsu.bypass.mute |
— | Exempts the holder from mute enforcement |
vsu.command.back |
0 | /back, /backdeath |
vsu.command.crate |
0 | /crate list, /crate open, /crate prizes, /crate key balance |
vsu.command.home |
0 | /home, /homes |
vsu.command.kit |
0 | /kit, /kits |
vsu.command.message |
0 | /msg, /tell, /r, /reply, /ignore |
vsu.command.nick |
0 | /nick |
vsu.command.sethome |
0 | /sethome, /delhome |
vsu.command.spawn |
0 | /spawn |
vsu.command.tpa |
0 | /tpa, /tpahere, /tpaccept, /tpdeny |
vsu.command.utility |
0 | /hat, /workbench, /seen, /ping, /near, /list, /getpos, /playtime, /suicide, /ext |
vsu.command.warp |
0 | /warp, /warps |
vsu.mod.ban |
3 | /ban, /tempban, /unban, /banlist |
vsu.mod.kick |
2 | /kick |
vsu.mod.mute |
3 | /mute, /tempmute, /unmute |
vsu.mod.warn |
2 | /warn, /warnings, /clearwarnings |
The same node can carry two different operator fallbacks depending on the
command registration. vsu.command.utility is the clear case: most of its
commands fall back to 0, but /more, /clear, /repair, and /anvil declare
fallback 2, and the target form of /ext declares 2 as well. Granting the node
through LuckPerms gives all of them at once.
Bypass#
There are two bypass nodes, and they behave differently.
vsu.bypass.mute is read at enforcement time. A player holding it is reported as
not muted even when an active MUTE row exists for them. The row stays in the
database and stays visible in the list commands; only enforcement is skipped.
Revoke the node and the existing mute takes effect on the next chat message with
no administrative action needed. That property is deliberate and is the safest way
to test the mute system on a staff alt.
vsu.bypass.ban is read at login. A player holding it is allowed to join despite
an active BAN row, and the bypass is written to the server log with the player's
uuid and name. It is checked in the Fabric and NeoForge join listeners, and only
when LuckPerms is present — with LuckPerms absent there is no bypass path and any
active ban stands.
vsu.bypass.ban is a standing un-ban
Anyone holding this node can join for as long as the node is set, and the active ban row does not expire while they hold it. Granting it to a group that regular staff inherit is the same as removing their bans permanently. Use a throwaway group for a test, then delete the group.
Grant either node per user, not per group:
lp user TestAlt permission set vsu.bypass.mute true
lp user TestAlt permission set vsu.bypass.mute false
lp creategroup ban-test
lp group ban-test permission set vsu.bypass.ban true
lp user TestAlt parent add ban-test
# test, then tear the group down
lp user TestAlt parent remove ban-test
lp deletegroup ban-test
Never wildcard the bypass namespace
Granting a namespace wildcard that covers the bypass family hands the exemptions to every member of the group, including anyone who inherits it later. A wildcard here silently exempts its holders from both mute and ban enforcement. Bypass grants should stay per-user and time-boxed.
The loader-side login listener also consults a ban-exemption grant before it
disconnects a banned player. That grant is not part of the published node tree in
2.2.0 and is not documented here; treat any ban exemption as unsupported and
avoid relying on it.
Group recipes#
The recipes below are a starting point, not a policy. They assume LuckPerms
lp CLI access from console and a group hierarchy built bottom-up.
default-player#
Every player command whose fallback is 0, so non-op players work without individual grants.
lp creategroup default-player
lp group default-player parent add default
lp group default-player permission set vsu.command.home true
lp group default-player permission set vsu.command.sethome true
lp group default-player permission set vsu.command.tpa true
lp group default-player permission set vsu.command.back true
lp group default-player permission set vsu.command.warp true
lp group default-player permission set vsu.command.spawn true
lp group default-player permission set vsu.command.nick true
lp group default-player permission set vsu.command.kit true
lp group default-player permission set vsu.command.message true
lp group default-player permission set vsu.command.utility true
lp group default-player permission set vsu.command.crate true
trusted#
Verified members. Same as default-player; raise it when you want to hand out
extra conveniences such as the crate administration tree.
lp creategroup trusted
lp group trusted parent add default-player
builder#
Adds the world-shaping utilities a build team needs.
lp creategroup builder
lp group builder parent add trusted
lp group builder permission set vsu.admin.fly true
lp group builder permission set vsu.admin.gamemode true
lp group builder permission set vsu.admin.heal true
lp group builder permission set vsu.admin.teleport true
lp group builder permission set vsu.admin.setspawn true
mod#
Moderation staff, with the peeking and broadcast tools they need to investigate.
lp creategroup mod
lp group mod parent add builder
lp group mod permission set vsu.mod.kick true
lp group mod permission set vsu.mod.warn true
lp group mod permission set vsu.mod.mute true
lp group mod permission set vsu.mod.ban true
lp group mod permission set vsu.admin.peek true
lp group mod permission set vsu.admin.vanish true
lp group mod permission set vsu.admin.broadcast true
admin#
Full world and warp authority.
lp creategroup admin
lp group admin parent add mod
lp group admin permission set vsu.admin.world true
lp group admin permission set vsu.admin.smite true
lp group admin permission set vsu.admin.god true
lp group admin permission set vsu.admin.warp true
lp group admin permission set vsu.admin.lag true
lp group admin permission set vsu.admin.crate true
owner#
Adds VSU management. This is the only group that should hold
vsu.admin.manage, because it covers /vonixsu reload and /kit reload.
lp creategroup owner
lp group owner parent add admin
lp group owner permission set vsu.admin.manage true
Assigning a player:
lp user Steve parent add trusted
lp user Alex parent set admin
The v1.6.0 lockout#
1.6.0 shipped LuckPerms as authoritative. When LP was present the operator
fallback was never consulted, so a node that had not been explicitly granted read
as a denial for every non-console source. Installing LuckPerms without also
granting the full player node set locked every player, including operators, out
of every command.
1.6.1 changed the composition to the union described above and that behaviour
is what 2.2.0 ships. Two notes for anyone reading older material:
- The union is not a fallback chain. LP grant and operator level are checked with OR, not in sequence with a hard stop.
- If you are somehow still on a 1.6.0 jar, the emergency workaround is to grant
an all-commands wildcard on each namespace a group needs — the player namespace
on
default, the admin namespace onadmin, the moderation namespace onmod. LuckPerms resolves a trailing wildcard segment during inheritance, so the exact node VSU queries reads as granted without per-command lines.
Wildcards belong in a temporary recovery step, not in a permanent group config. They grant future commands automatically, which means a later release that adds a destructive command also adds it to every group holding the wildcard. Replace them with explicit nodes once the server is reachable again.
Pitfalls#
The utility node is broad. vsu.command.utility covers a dozen commands with
mixed sensitivity: /hat and /ping next to /more, /clear, and /repair.
Granting it for the harmless ones also grants inventory clearing and item repair.
Because the fallback differs per command, a group with the node gets the op-2
commands too. Split the risk by granting the node only to groups you would trust
with /clear, or accept that the node is one unit.
/whois is a staff command. Older reference material lists it as a player
command on vsu.command.utility at op 0. Source gates it on vsu.admin.peek at
op 2 because it reveals another player's position, health, and food. Grant the
peek node if you want players to have it.
Four conveniences need op 2. /more, /clear, /repair, and /anvil are
registered on vsu.command.utility with an operator fallback of 2, not 0. A
non-op player with the node gets them; a non-op player without it does not, even
though /hat and /workbench on the same node work for everyone.
Operator level is sticky in the other direction. De-op is the only way to
remove an operator's access. If you need an op who cannot use /gm, the answer
is not a node — it is not being op.
Console bypass hides permission bugs. A command that fails for a player but works from console is almost always a permission problem, not a code problem. Test as a non-op player before concluding a command is broken.
Mute enforcement is not a node. A muted player is blocked by the loader chat
hook, so no vsu.command.message grant will let them talk. See
Moderation for the enforcement path.
There are no cooldown bypass nodes. The bypass family holds one entry,
vsu.bypass.mute. Anything documenting a home or TPA cooldown exemption is
describing a node that was never registered; no cooldown bypass exists in this
build.
Related pages#
- Commands — syntax and per-command nodes
- Moderation — punishment workflows
- Troubleshooting — diagnosing denials