Motivation
Every existing aid (help text, error messages, GUIs) only helps after the player presses enter. Brigadier is the only mechanism that helps while they type: the client shows subcommand suggestions natively, red-underlines invalid input, and renders suggestion tooltips — no reading required.
Today BentoBox registers commands by reflecting into Bukkit's SimpleCommandMap (CommandsManager.registerCommand, src/main/java/world/bentobox/bentobox/managers/CommandsManager.java). That is fragile, deprecated territory on modern Paper, and it presents every BentoBox command to the client as an opaque greedy string — the client can't help the player at all. Paper's Brigadier API (io.papermc.paper.command.brigadier.Commands, registered via LifecycleEvents.COMMANDS) is in our current paper-api 26.1.2 compile target.
Proposal: three incremental phases
CompositeCommand is public API compiled against by every addon — the addon-facing contract must not change. The Brigadier layer wraps the existing tree; addons keep registering CompositeCommands exactly as today and gain client-side UX for free.
Phase 1 — registration shim (no behavior change). Register each top-level CompositeCommand as a Brigadier literal with a greedy-string argument that delegates to the existing execute(...) dispatch. Deletes the SimpleCommandMap reflection. Risk is low; this is the spike to do first.
Phase 2 — expose the subcommand tree. Auto-generate Brigadier literal nodes from the CompositeCommand subcommand/alias tree so clients see go, team, invite, … natively as they type. Map each command's existing tabComplete() into a Brigadier SuggestionProvider (with tooltips from the command descriptions). This is where most of the player-facing win lands, and it is derivable mechanically from the tree we already have.
Phase 3 — typed arguments. Custom ArgumentTypes for the recurring argument shapes (online player, island/home name, rank). Gets real red-underline validation and quoting-free multi-word island names.
Constraints to design around
- Dynamic registration: Brigadier registration happens during the
LifecycleEvents.COMMANDS lifecycle event, but game mode addons register commands during BentoBox enable, and hooks/reloads can re-register later. Need to confirm the reload story (Paper supports re-running registrar callbacks; /bentobox reload behavior must be verified).
- Aliases per game mode (
/is, /ob, …) come from addon config — the shim must register all of them.
- Fallback: keep the
SimpleCommandMap path as a fallback for non-Paper servers if Spigot support is still required; gate via the existing server-compat detection.
Where to start
- Phase 1 spike in
CommandsManager: one flag-guarded alternative registration path, validated against a game mode addon (BSkyBlock) for command execution, tab completion, permissions, and console senders.
- Then measure: the command-friction telemetry (see related issue) should show
unknown-subcommand rates dropping once Phase 2 ships — that is the success metric.
Related design issues
Motivation
Every existing aid (help text, error messages, GUIs) only helps after the player presses enter. Brigadier is the only mechanism that helps while they type: the client shows subcommand suggestions natively, red-underlines invalid input, and renders suggestion tooltips — no reading required.
Today BentoBox registers commands by reflecting into Bukkit's
SimpleCommandMap(CommandsManager.registerCommand,src/main/java/world/bentobox/bentobox/managers/CommandsManager.java). That is fragile, deprecated territory on modern Paper, and it presents every BentoBox command to the client as an opaque greedy string — the client can't help the player at all. Paper's Brigadier API (io.papermc.paper.command.brigadier.Commands, registered viaLifecycleEvents.COMMANDS) is in our currentpaper-api 26.1.2compile target.Proposal: three incremental phases
CompositeCommandis public API compiled against by every addon — the addon-facing contract must not change. The Brigadier layer wraps the existing tree; addons keep registeringCompositeCommands exactly as today and gain client-side UX for free.Phase 1 — registration shim (no behavior change). Register each top-level
CompositeCommandas a Brigadier literal with a greedy-string argument that delegates to the existingexecute(...)dispatch. Deletes theSimpleCommandMapreflection. Risk is low; this is the spike to do first.Phase 2 — expose the subcommand tree. Auto-generate Brigadier literal nodes from the
CompositeCommandsubcommand/alias tree so clients seego,team,invite, … natively as they type. Map each command's existingtabComplete()into a BrigadierSuggestionProvider(with tooltips from the command descriptions). This is where most of the player-facing win lands, and it is derivable mechanically from the tree we already have.Phase 3 — typed arguments. Custom
ArgumentTypes for the recurring argument shapes (online player, island/home name, rank). Gets real red-underline validation and quoting-free multi-word island names.Constraints to design around
LifecycleEvents.COMMANDSlifecycle event, but game mode addons register commands during BentoBox enable, and hooks/reloads can re-register later. Need to confirm the reload story (Paper supports re-running registrar callbacks;/bentobox reloadbehavior must be verified)./is,/ob, …) come from addon config — the shim must register all of them.SimpleCommandMappath as a fallback for non-Paper servers if Spigot support is still required; gate via the existing server-compat detection.Where to start
CommandsManager: one flag-guarded alternative registration path, validated against a game mode addon (BSkyBlock) for command execution, tab completion, permissions, and console senders.unknown-subcommandrates dropping once Phase 2 ships — that is the success metric.Related design issues