Skip to main content
Version: Minecraft 26.2

Commands and permissions

Commands​

mod.commands().register(CommandNode.literal("showcase")
.then(CommandNode.literal("info").executes(context -> {
context.source().sendMessage("Native Showcase");
return 1;
}))
.then(CommandNode.literal("add")
.then(CommandNode.argument("a", CommandArgumentType.integer())
.then(CommandNode.argument("b", CommandArgumentType.integer())
.executes(ctx -> ctx.getInteger("a") + ctx.getInteger("b"))))));
  • Commands are installed into the game's Brigadier tree. They are installed on every server start and every /reload.
  • The return value of executes is the command's result value (received by /execute store and by runCommand in game tests).
  • Report a failure by throwing CommandFailure. You can also send only a failure message with context.source().sendFailure(text).
  • If two mods register the same top-level command, Poly Mod Loader merges the trees and logs a POLY-COMMAND-001 warning.

Argument types​

CommandArgumentTypeHow to read it
integer(), integer(min, max)getInteger(name)
decimal()getDouble(name)
bool()getBoolean(name)
word(), string(), greedyString()getString(name) (one word; a word or quoted string; the whole rest of the line)
blockPos()getBlockPos(name)
player()getPlayer(name)

CommandSource​

context.source() is who ran the command: name(), sendMessage, sendFailure, hasPermission(level), hasPermission(node), player() (Optional), world(), blockPos().

.then(CommandNode.argument("pos", CommandArgumentType.blockPos()).executes(context -> {
context.source().world().setBlock(context.getBlockPos("pos"), GLOW_BLOCK);
return 1;
}))

Permissions​

Permission levels​

CommandNode.literal("reset").requiresPermission(2); // 0..4, the game's operator level

Permission nodes​

PermissionNode PLACE = mod.permissions().node("place", 2); // my_mod.place, default operator level 2

mod.commands().register(CommandNode.literal("ruby")
.then(CommandNode.literal("place").requiresPermission(PLACE)
.then(CommandNode.argument("pos", CommandArgumentType.blockPos()).executes(context -> {
context.source().world().setBlock(context.getBlockPos("pos"), RUBY_BLOCK);
return 1;
}))));

player.hasPermission(PLACE);
  • A node name is <mod id>.<path>.
  • The command node's level and the permission node are checked together. The console and command blocks are judged by level.

Permission providers​

A permission mod registers a provider to make decisions.

mod.permissions().provider((player, node) ->
node.equals(SECRET) && isTrusted(player) ? PermissionResult.ALLOW : PermissionResult.UNDECIDED);
  • Providers are called in registration order for every permission check of every mod. A provider returns ALLOW, DENY, or UNDECIDED.
  • If no provider decides, Poly Mod Loader uses the node's default operator level.
  • If a provider throws an exception, Poly Mod Loader skips that provider and logs POLY-PERMISSION-003.

Error codes​

CodeMeaning
POLY-COMMAND-001Two mods registered the same top-level command (warning, trees merged)
POLY-COMMAND-002Registered after registration closed
POLY-PERMISSION-001Invalid or duplicate permission node
POLY-PERMISSION-002Declared after registration closed
POLY-PERMISSION-003Provider exception (that provider is skipped)
Buy me a coffee