@@ -40,12 +40,7 @@ public LiteralCommandNode<T> buildLiteral(
4040 .executes (executor );
4141
4242 LiteralCommandNode <T > root = builder .build ();
43-
44- if (node .isLeaf ()) {
45- registerParams (node , root , suggestionProvider , executor );
46- } else if (blade .configuration ().registerDefaultHelpArguments () && !node .children ().isEmpty ()) {
47- registerHelpParams (node , root , suggestionProvider , executor );
48- }
43+ registerNodeData (node , root , suggestionProvider , executor );
4944
5045 for (CommandTreeNode subcommand : node .children ().values ()) {
5146 registerSubCommand (root ,
@@ -54,6 +49,13 @@ public LiteralCommandNode<T> buildLiteral(
5449 executor );
5550 }
5651
52+ if (hasHiddenCommand (node )) {
53+ BrigadierCompat .setClientNode (
54+ root ,
55+ buildClientLiteral (node , label , suggestionProvider , executor )
56+ );
57+ }
58+
5759 return root ;
5860 }
5961
@@ -70,15 +72,83 @@ private void registerSubCommand(
7072
7173 LiteralCommandNode <T > subcommandNode = builder .build ();
7274 root .addChild (subcommandNode );
75+ registerNodeData (node , subcommandNode , suggestionProvider , executor );
7376
74- if (node .isLeaf ()) {
75- registerParams (node , subcommandNode , suggestionProvider , executor );
76- } else if (blade .configuration ().registerDefaultHelpArguments () && !node .children ().isEmpty ()) {
77- registerHelpParams (node , subcommandNode , suggestionProvider , executor );
77+ for (CommandTreeNode child : node .children ().values ()) {
78+ registerSubCommand (subcommandNode , child , suggestionProvider , executor );
79+ }
80+ }
81+
82+ @ NotNull
83+ private LiteralCommandNode <T > buildClientLiteral (@ NotNull CommandTreeNode node ,
84+ @ NotNull String label ,
85+ @ NotNull SuggestionProvider <T > suggestionProvider ,
86+ @ NotNull Command <T > executor ) {
87+ boolean visibleLeaf = node .command () != null && !node .command ().hidden ();
88+
89+ LiteralArgumentBuilder <T > builder = LiteralArgumentBuilder .<T >literal (label )
90+ .requires (createClientVisibilityPredicate (node ));
91+
92+ if (visibleLeaf ) {
93+ builder .executes (executor );
94+ }
95+
96+ LiteralCommandNode <T > root = builder .build ();
97+
98+ if (visibleLeaf ) {
99+ registerNodeData (node , root , suggestionProvider , executor );
100+ }
101+
102+ for (CommandTreeNode subcommand : node .children ().values ()) {
103+ if (!hasVisibleCommand (subcommand )) {
104+ continue ;
105+ }
106+
107+ root .addChild (buildClientSubCommand (subcommand , suggestionProvider , executor ));
108+ }
109+
110+ return root ;
111+ }
112+
113+ @ NotNull
114+ private LiteralCommandNode <T > buildClientSubCommand (@ NotNull CommandTreeNode node ,
115+ @ NotNull SuggestionProvider <T > suggestionProvider ,
116+ @ NotNull Command <T > executor ) {
117+ String label = node .label ();
118+ boolean visibleLeaf = node .command () != null && !node .command ().hidden ();
119+
120+ LiteralArgumentBuilder <T > builder = LiteralArgumentBuilder .<T >literal (label )
121+ .requires (createClientVisibilityPredicate (node ));
122+
123+ if (visibleLeaf ) {
124+ builder .executes (executor );
125+ }
126+
127+ LiteralCommandNode <T > subcommandNode = builder .build ();
128+
129+ if (visibleLeaf ) {
130+ registerNodeData (node , subcommandNode , suggestionProvider , executor );
78131 }
79132
80133 for (CommandTreeNode child : node .children ().values ()) {
81- registerSubCommand (subcommandNode , child , suggestionProvider , executor );
134+ if (!hasVisibleCommand (child )) {
135+ continue ;
136+ }
137+
138+ subcommandNode .addChild (buildClientSubCommand (child , suggestionProvider , executor ));
139+ }
140+
141+ return subcommandNode ;
142+ }
143+
144+ private void registerNodeData (@ NotNull CommandTreeNode node ,
145+ @ NotNull CommandNode <T > commandNode ,
146+ @ NotNull SuggestionProvider <T > suggestionProvider ,
147+ @ NotNull Command <T > brigadierCommand ) {
148+ if (node .isLeaf ()) {
149+ registerParams (node , commandNode , suggestionProvider , brigadierCommand );
150+ } else if (blade .configuration ().registerDefaultHelpArguments () && !node .children ().isEmpty ()) {
151+ registerHelpParams (node , commandNode , suggestionProvider , brigadierCommand );
82152 }
83153 }
84154
@@ -144,8 +214,7 @@ private void registerParams(@NotNull CommandTreeNode node,
144214 @ NotNull
145215 private Predicate <T > createPermissionPredicate (@ NotNull CommandTreeNode node ) {
146216 return sender -> {
147- Sender <?> wrappedSender = wrapper .apply (converter .apply (sender ));
148- Context context = new Context (blade , wrappedSender , "" , new String [0 ]);
217+ Context context = createContext (sender );
149218
150219 if (node .command () != null ) {
151220 return node .command ().hasPermission (context );
@@ -159,6 +228,17 @@ private Predicate<T> createPermissionPredicate(@NotNull CommandTreeNode node) {
159228 };
160229 }
161230
231+ @ NotNull
232+ private Predicate <T > createClientVisibilityPredicate (@ NotNull CommandTreeNode node ) {
233+ return sender -> hasVisibleAccessibleCommand (node , createContext (sender ));
234+ }
235+
236+ @ NotNull
237+ private Context createContext (@ NotNull T sender ) {
238+ Sender <?> wrappedSender = wrapper .apply (converter .apply (sender ));
239+ return new Context (blade , wrappedSender , "" , new String [0 ]);
240+ }
241+
162242 private boolean hasAccessibleCommand (@ NotNull CommandTreeNode node ,
163243 @ NotNull Context context ) {
164244 if (node .isLeaf ()) {
@@ -177,6 +257,58 @@ private boolean hasAccessibleCommand(@NotNull CommandTreeNode node,
177257 return false ;
178258 }
179259
260+ private boolean hasVisibleCommand (@ NotNull CommandTreeNode node ) {
261+ if (node .isLeaf ()) {
262+ BladeCommand cmd = node .command ();
263+ if (cmd != null && !cmd .hidden ()) {
264+ return true ;
265+ }
266+ }
267+
268+ for (CommandTreeNode child : node .children ().values ()) {
269+ if (hasVisibleCommand (child )) {
270+ return true ;
271+ }
272+ }
273+
274+ return false ;
275+ }
276+
277+ private boolean hasHiddenCommand (@ NotNull CommandTreeNode node ) {
278+ if (node .isLeaf ()) {
279+ BladeCommand cmd = node .command ();
280+ if (cmd != null && cmd .hidden ()) {
281+ return true ;
282+ }
283+ }
284+
285+ for (CommandTreeNode child : node .children ().values ()) {
286+ if (hasHiddenCommand (child )) {
287+ return true ;
288+ }
289+ }
290+
291+ return false ;
292+ }
293+
294+ private boolean hasVisibleAccessibleCommand (@ NotNull CommandTreeNode node ,
295+ @ NotNull Context context ) {
296+ if (node .isLeaf ()) {
297+ BladeCommand cmd = node .command ();
298+ if (cmd != null && !cmd .hidden () && cmd .hasPermission (context )) {
299+ return true ;
300+ }
301+ }
302+
303+ for (CommandTreeNode child : node .children ().values ()) {
304+ if (hasVisibleAccessibleCommand (child , context )) {
305+ return true ;
306+ }
307+ }
308+
309+ return false ;
310+ }
311+
180312 @ NotNull
181313 private ArgumentType <Object > mapBrigadierArgument (@ NotNull BladeCommand command ,
182314 @ NotNull BladeParameter parameter ) {
@@ -262,5 +394,4 @@ private ArgumentType<Object> mapBrigadierArgument(@NotNull BladeCommand command,
262394 //noinspection unchecked
263395 return (ArgumentType <Object >) type ;
264396 }
265-
266397}
0 commit comments