@@ -41,63 +41,209 @@ public CommandInvoker(CommandManager<T, S> manager) {
4141 * @return true if a command handler was executed or a message sent; false if command not found
4242 */
4343 public boolean invoke (S source , String base , String [] rawArgs ) {
44- // find matching node
44+ Optional <CommandContext <T , S >> contextOpt = findCommandContext (base , rawArgs );
45+ if (!contextOpt .isPresent ()) {
46+ return false ;
47+ }
48+
49+ CommandContext <T , S > context = contextOpt .get ();
50+
51+ if (!validateCommandExecution (source , context )) {
52+ return true ;
53+ }
54+
55+ return executeCommand (source , context );
56+ }
57+
58+ /**
59+ * Find and prepare command context.
60+ * @param base the base command label
61+ * @param rawArgs the raw arguments
62+ * @return the command context if found
63+ */
64+ private Optional <CommandContext <T , S >> findCommandContext (String base , String [] rawArgs ) {
4565 Optional <MatchResult <T , S >> found = manager .getCommands ().findNode (base , rawArgs );
46- if (!found .isPresent ()) return false ;
66+ if (!found .isPresent ()) {
67+ return Optional .empty ();
68+ }
69+
4770 MatchResult <T , S > result = found .get ();
4871 CommandTree .CommandNode <T , S > node = result .node ;
4972 Optional <Command <T , S >> cmdOpt = node .getCommand ();
50- if (!cmdOpt .isPresent ()) return false ;
73+
74+ if (!cmdOpt .isPresent ()) {
75+ return Optional .empty ();
76+ }
77+
5178 Command <T , S > command = cmdOpt .get ();
5279 String label = node .getFullLabel () != null ? node .getFullLabel () : base ;
5380 String [] args = result .args ;
5481
55- // in-game check
82+ return Optional .of (new CommandContext <>(command , label , args ));
83+ }
84+
85+ /**
86+ * Validate command execution conditions (in-game, permissions, requirements, usage).
87+ * @param source the command sender
88+ * @param context the command context
89+ * @return true if all validations passed, false otherwise (message already sent to user)
90+ */
91+ private boolean validateCommandExecution (S source , CommandContext <T , S > context ) {
92+ return checkInGameOnly (source , context .command )
93+ && checkPermission (source , context .command )
94+ && checkRequirements (source , context .command )
95+ && checkUsage (source , context );
96+ }
97+
98+ /**
99+ * Check if command requires in-game execution.
100+ * @param source the command sender
101+ * @param command the command to check
102+ * @return true if check passed or not applicable
103+ */
104+ private boolean checkInGameOnly (S source , Command <T , S > command ) {
56105 if (command .inGameOnly () && !manager .getPlatform ().isPlayer (source )) {
57106 manager .getPlatform ().sendMessage (source , manager .getMessageHandler ().getOnlyInGameMessage ());
58- return true ;
107+ return false ;
59108 }
60- // permission check
109+ return true ;
110+ }
111+
112+ /**
113+ * Check if sender has required permission.
114+ * @param source the command sender
115+ * @param command the command to check
116+ * @return true if check passed or no permission required
117+ */
118+ private boolean checkPermission (S source , Command <T , S > command ) {
61119 String perm = command .getPermission ();
62120 if (!perm .isEmpty () && !manager .getPlatform ().hasPermission (source , perm )) {
63121 manager .getPlatform ().sendMessage (source , manager .getMessageHandler ().getNoPermissionMessage ());
64- return true ;
122+ return false ;
65123 }
66- // requirements
124+ return true ;
125+ }
126+
127+ /**
128+ * Check if all requirements are satisfied.
129+ * @param source the command sender
130+ * @param command the command to check
131+ * @return true if all requirements passed
132+ */
133+ private boolean checkRequirements (S source , Command <T , S > command ) {
67134 for (Requirement <S > req : command .getRequirements ()) {
68135 if (!req .check (source )) {
69- String msg = req .errorMessage ().isEmpty ()
70- ? manager .getMessageHandler ().getRequirementMessage ().replace ("%requirement%" , req .getClass ().getSimpleName ())
71- : req .errorMessage ();
136+ String msg = buildRequirementMessage (req );
72137 manager .getPlatform ().sendMessage (source , msg );
73- return true ;
138+ return false ;
74139 }
75140 }
76- // usage check
141+ return true ;
142+ }
143+
144+ /**
145+ * Build error message for failed requirement.
146+ * @param req the failed requirement
147+ * @return the error message
148+ */
149+ private String buildRequirementMessage (Requirement <S > req ) {
150+ return req .errorMessage ().isEmpty ()
151+ ? manager .getMessageHandler ().getRequirementMessage ()
152+ .replace ("%requirement%" , req .getClass ().getSimpleName ())
153+ : req .errorMessage ();
154+ }
155+
156+ /**
157+ * Check if argument count is valid.
158+ * @param source the command sender
159+ * @param context the command context
160+ * @return true if usage is correct
161+ */
162+ private boolean checkUsage (S source , CommandContext <T , S > context ) {
163+ Command <T , S > command = context .command ;
164+ String [] args = context .args ;
165+
77166 int min = command .getArgs ().size ();
78167 int max = command .isInfiniteArgs () ? Integer .MAX_VALUE : min + command .getOptinalArgs ().size ();
168+
79169 if (args .length < min || args .length > max ) {
80- String usage = command .getUsage ().isEmpty ()
81- ? command .generateDefaultUsage (manager .getPlatform (), source , label )
82- : command .getUsage ();
170+ String usage = buildUsageMessage (source , context );
83171 manager .getPlatform ().sendMessage (source , usage );
84- return true ;
172+ return false ;
85173 }
86- // parse and execute
174+ return true ;
175+ }
176+
177+ /**
178+ * Build usage message for command.
179+ * @param source the command sender
180+ * @param context the command context
181+ * @return the usage message
182+ */
183+ private String buildUsageMessage (S source , CommandContext <T , S > context ) {
184+ Command <T , S > command = context .command ;
185+ String label = context .label ;
186+
187+ return command .getUsage ().isEmpty ()
188+ ? command .generateDefaultUsage (manager .getPlatform (), source , label )
189+ : command .getUsage ();
190+ }
191+
192+ /**
193+ * Execute the command with error handling.
194+ * @param source the command sender
195+ * @param context the command context
196+ * @return true if execution succeeded or error was handled, false for internal errors
197+ */
198+ private boolean executeCommand (S source , CommandContext <T , S > context ) {
87199 try {
88- Arguments parsed = manager .parse (command , args );
89- command .execute (source , parsed );
200+ Arguments parsed = manager .parse (context .command , context .args );
201+ context .command .execute (source , parsed );
202+ return true ;
90203 } catch (TypeArgumentNotExistException e ) {
91- manager .getPlatform ().sendMessage (source , "&cInternal error: invalid argument type" );
92- return false ;
204+ return handleTypeArgumentError (source );
93205 } catch (ArgumentIncorrectException e ) {
94- String msg = manager .getMessageHandler ().getArgNotRecognized ().replace ("%arg%" , e .getInput ());
95- manager .getPlatform ().sendMessage (source , msg );
96- return true ;
206+ return handleArgumentIncorrectError (source , e );
97207 }
208+ }
209+
210+ /**
211+ * Handle type argument not exist error.
212+ * @param source the command sender
213+ * @return false to indicate internal error
214+ */
215+ private boolean handleTypeArgumentError (S source ) {
216+ manager .getPlatform ().sendMessage (source , "&cInternal error: invalid argument type" );
217+ return false ;
218+ }
219+
220+ /**
221+ * Handle incorrect argument error.
222+ * @param source the command sender
223+ * @param e the exception
224+ * @return true to indicate error was handled
225+ */
226+ private boolean handleArgumentIncorrectError (S source , ArgumentIncorrectException e ) {
227+ String msg = manager .getMessageHandler ().getArgNotRecognized ().replace ("%arg%" , e .getInput ());
228+ manager .getPlatform ().sendMessage (source , msg );
98229 return true ;
99230 }
100231
232+ /**
233+ * Internal context class to hold command execution data.
234+ */
235+ private static class CommandContext <T , S > {
236+ final Command <T , S > command ;
237+ final String label ;
238+ final String [] args ;
239+
240+ CommandContext (Command <T , S > command , String label , String [] args ) {
241+ this .command = command ;
242+ this .label = label ;
243+ this .args = args ;
244+ }
245+ }
246+
101247 /**
102248 * Suggests command completions based on the provided source, base label, and arguments.
103249 * This method checks for available tab completers and filters suggestions based on the current input.
0 commit comments