11package io .github .simplexdev .simplexcore .command ;
22
33import io .github .simplexdev .api .annotations .CommandInfo ;
4- import io .github .simplexdev .simplexcore .command . defaults . DefaultCommand ;
4+ import io .github .simplexdev .simplexcore .SimplexCorePlugin ;
55import io .github .simplexdev .simplexcore .module .SimplexModule ;
66import io .github .simplexdev .simplexcore .utils .ReflectionTools ;
7- import io .github .simplexdev .simplexcore .SimplexCorePlugin ;
8- import org .bukkit .Bukkit ;
9- import org .bukkit .command .*;
7+ import org .bukkit .command .CommandExecutor ;
8+ import org .bukkit .command .CommandMap ;
9+ import org .bukkit .command .PluginCommand ;
10+ import org .bukkit .command .TabCompleter ;
1011import org .bukkit .plugin .Plugin ;
1112import org .bukkit .plugin .SimplePluginManager ;
1213import org .jetbrains .annotations .NotNull ;
2021
2122public final class CommandLoader {
2223 private Reflections reflections ;
24+ private ClassLoader classLoader ;
25+ private SimplexModule <?> plugin ;
2326 private static final CommandLoader instance = new CommandLoader ();
27+ private final Registry registry = new Registry ();
2428
2529 /**
2630 * @return A Singleton Pattern instance of this class.
@@ -38,38 +42,42 @@ public static CommandLoader getInstance() {
3842 * If the class provided does not have the {@link CommandInfo} annotation, the loader will throw a new
3943 * {@link MissingResourceException} and will not load your plugin's commands.
4044 * If the class provided does not extend {@link SimplexCommand}, the loader will throw a new
41- * {@link RuntimeException } and your commands will not be loaded.
45+ * {@link CommandLoaderException } and your commands will not be loaded.
4246 * </p>
4347 *
4448 * @param clazz The command class to load from
4549 * @return An instance of this where the classpath has been prepared for loading the commands.
4650 */
47- public <T extends SimplexCommand > CommandLoader classpath (Class <T > clazz ) {
51+ public <T extends SimplexCommand > CommandLoader classpath (SimplexModule <?> plugin , Class <T > clazz ) {
4852 if (clazz == null ) {
49- throw new IllegalStateException ("The class provided cannot be found!" );
53+ throw new IllegalArgumentException ("The class provided cannot be found!" );
5054 }
5155
5256 if (!clazz .isAnnotationPresent (CommandInfo .class )) {
5357 throw new MissingResourceException ("Cannot register this class as the main resource location!" , clazz .getSimpleName (), "@CommandInfo" );
5458 }
5559
5660 if (!SimplexCommand .class .isAssignableFrom (clazz )) {
57- throw new RuntimeException ("Your command must extend SimplexCommand.class for it to be used as the reference point for loading commands." );
61+ throw new CommandLoaderException ("Your command must extend SimplexCommand.class for it to be used as the reference point for loading commands." );
5862 }
5963
60- reflections = ReflectionTools .reflect (clazz );
64+ this .reflections = ReflectionTools .reflect (clazz );
65+ this .plugin = plugin ;
66+ this .classLoader = plugin .getClass ().getClassLoader ();
6167
6268 return this ;
6369 }
6470
6571 /**
6672 * Loads all the commands from the specified classpath.
67- * This should be used immediately after {@link CommandLoader#classpath(Class)} has been called.
73+ * This should be used immediately after {@link CommandLoader#classpath(SimplexModule, Class)} has been called.
6874 * If used before, an exception will be thrown, and your commands will not be loaded.
69- *
70- * @param plugin An instance of your plugin to assign as the parent plugin for each command.
7175 */
72- public void load (SimplexModule <?> plugin ) {
76+ public void load () {
77+ if (reflections == null || plugin == null || classLoader == null ) {
78+ throw new CommandLoaderException ("Please run CommandLoader#classpath(SimplexModule, Class) first!" );
79+ }
80+
7381 reflections .getTypesAnnotatedWith (CommandInfo .class ).forEach (annotated -> {
7482 CommandInfo info = annotated .getDeclaredAnnotation (CommandInfo .class );
7583
@@ -89,7 +97,7 @@ public void load(SimplexModule<?> plugin) {
8997 return ;
9098 }
9199
92- PluginCommand command = Registry .create (plugin , info .name ().toLowerCase ());
100+ PluginCommand command = registry .create (plugin , info .name ().toLowerCase ());
93101 command .setAliases (Arrays .asList (info .aliases ().split ("," )));
94102 command .setDescription (info .description ());
95103 command .setExecutor (getExecutorFromName (info .name ()));
@@ -98,7 +106,7 @@ public void load(SimplexModule<?> plugin) {
98106 command .setPermissionMessage (info .permissionMessage ());
99107 command .setTabCompleter (getTabFromName (info .name ()));
100108 command .setUsage (info .usage ());
101- Registry .registerCommand (command );
109+ registry .registerCommand (command );
102110 });
103111 }
104112
@@ -110,28 +118,27 @@ public void load(SimplexModule<?> plugin) {
110118 * @param name The name of the command.
111119 * @return An instance of the command class as a CommandExecutor.
112120 */
113- public CommandExecutor getExecutorFromName (String name ) {
114- for (Class <? extends CommandExecutor > obj : reflections .getSubTypesOf (CommandExecutor .class )) {
121+ private CommandExecutor getExecutorFromName (String name ) {
122+ for (Class <? extends SimplexCommand > obj : reflections .getSubTypesOf (SimplexCommand .class )) {
115123 if (!obj .isAnnotationPresent (CommandInfo .class )) {
116- SimplexCorePlugin .getInstance ()
117- .getLogger ().warning (obj .getSimpleName ()
124+ plugin .getLogger ().warning (obj .getSimpleName ()
118125 + " is missing a required annotation: "
119126 + CommandInfo .class .getSimpleName ());
127+ continue ;
120128 }
121129
122130 CommandInfo info = obj .getDeclaredAnnotation (CommandInfo .class );
123131
124132 if (name .equalsIgnoreCase (info .name ())) {
125- try {
126- Constructor <? extends CommandExecutor > constr = obj .getDeclaredConstructor ();
127- constr .setAccessible (true );
128- return constr .newInstance ();
129- } catch (ReflectiveOperationException ignored ) {
130- return new DefaultCommand ();
133+ Constructor <? extends CommandExecutor > constr =
134+ ReflectionTools .getDeclaredConstructor (obj , SimplexModule .class );
135+ if (constr == null ) {
136+ throw new CommandLoaderException ("Constructor does not exist! Are you extending SimplexCommand properly?" );
131137 }
138+ return ReflectionTools .initConstructor (constr , plugin );
132139 }
133140 }
134- throw new RuntimeException ("Unable to assign a CommandExecutor from the provided classes!" );
141+ throw new CommandLoaderException ("Unable to assign a CommandExecutor from the provided classes!" );
135142 }
136143
137144 /**
@@ -143,52 +150,50 @@ public CommandExecutor getExecutorFromName(String name) {
143150 * @return The command as an instance of TabCompleter
144151 */
145152 @ Nullable
146- public TabCompleter getTabFromName (String name ) {
147- for (Class <? extends TabCompleter > obj : reflections .getSubTypesOf (TabCompleter .class )) {
153+ private TabCompleter getTabFromName (String name ) {
154+ for (Class <? extends SimplexCommand > obj : reflections .getSubTypesOf (SimplexCommand .class )) {
148155 if (!obj .isAnnotationPresent (CommandInfo .class )) {
149- SimplexCorePlugin .getInstance ()
150- .getLogger ().warning (obj .getSimpleName ()
156+ plugin .getLogger ().warning (obj .getSimpleName ()
151157 + " is missing required annotation: "
152158 + CommandInfo .class .getSimpleName ());
153159 continue ;
154160 }
155161
156162 CommandInfo info = obj .getDeclaredAnnotation (CommandInfo .class );
163+
157164 if (name .equalsIgnoreCase (info .name ())) {
158- try {
159- Constructor <? extends TabCompleter > constr = obj .getDeclaredConstructor ();
160- constr .setAccessible (true );
161- return constr .newInstance ();
162- } catch (ReflectiveOperationException ignored ) {
163- return new DefaultCommand ();
165+ Constructor <? extends TabCompleter > constr = ReflectionTools .getDeclaredConstructor (obj , SimplexModule .class );
166+ if (constr == null ) {
167+ throw new CommandLoaderException ("Constructor does not exist! Are you extending SimplexCommand properly?" );
164168 }
169+ return ReflectionTools .initConstructor (constr , plugin );
165170 }
166171 }
167- return null ;
172+ throw new CommandLoaderException ( "Unable to assign a TabCompleter from the provided classes!" ) ;
168173 }
169174
170175 /**
171176 * Registry class, which forces all necessary fields to accessible.
172177 */
173- private static class Registry {
174- private static final Constructor <PluginCommand > constructor ;
175- private static final Field cmdMapField ;
178+ private final class Registry {
179+ private final Constructor <PluginCommand > constructor ;
180+ private final Field cmdMapField ;
176181
177- static {
182+ public Registry () {
178183 constructor = ReflectionTools .getDeclaredConstructor (PluginCommand .class , String .class , Plugin .class );
179184 cmdMapField = ReflectionTools .getDeclaredField (SimplePluginManager .class , "commandMap" );
180185 }
181186
182- public static PluginCommand create (@ NotNull Plugin plugin , @ NotNull String name ) {
187+ public PluginCommand create (@ NotNull SimplexModule <?> plugin , @ NotNull String name ) {
183188 return ReflectionTools .initConstructor (constructor , name , plugin );
184189 }
185190
186- public static void registerCommand (PluginCommand command ) {
191+ public void registerCommand (PluginCommand command ) {
187192 try {
188- CommandMap map = (CommandMap ) cmdMapField .get (Bukkit . getPluginManager ());
193+ CommandMap map = (CommandMap ) cmdMapField .get (plugin . getManager ());
189194 map .register (command .getName ().toLowerCase (), command );
190195 } catch (IllegalAccessException e ) {
191- throw new RuntimeException (e );
196+ throw new CommandLoaderException (e );
192197 }
193198 }
194199 }
0 commit comments