From 5e0775850a53b46296e1f017c0dfb4cc61f86f3d Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 6 Sep 2021 14:33:22 -0700 Subject: [PATCH] remove TerraCommandManager --- .../com/dfsek/terra/AbstractTerraPlugin.java | 16 - .../terra/commands/TerraCommandManager.java | 294 ------------------ .../src/test/java/command/CommandTest.java | 242 -------------- .../dfsek/terra/bukkit/TerraBukkitPlugin.java | 9 - 4 files changed, 561 deletions(-) delete mode 100644 common/implementation/src/main/java/com/dfsek/terra/commands/TerraCommandManager.java delete mode 100644 common/implementation/src/test/java/command/CommandTest.java diff --git a/common/implementation/src/main/java/com/dfsek/terra/AbstractTerraPlugin.java b/common/implementation/src/main/java/com/dfsek/terra/AbstractTerraPlugin.java index cf85d1458..9e06a8703 100644 --- a/common/implementation/src/main/java/com/dfsek/terra/AbstractTerraPlugin.java +++ b/common/implementation/src/main/java/com/dfsek/terra/AbstractTerraPlugin.java @@ -19,8 +19,6 @@ import java.util.Optional; import com.dfsek.terra.api.Logger; import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.addon.TerraAddon; -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.exception.MalformedCommandException; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.PluginConfig; import com.dfsek.terra.api.event.EventManager; @@ -30,8 +28,6 @@ import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.util.generic.Lazy; import com.dfsek.terra.api.util.mutable.MutableBoolean; -import com.dfsek.terra.commands.CommandUtil; -import com.dfsek.terra.commands.TerraCommandManager; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfigImpl; import com.dfsek.terra.config.lang.LangUtil; @@ -62,8 +58,6 @@ public abstract class AbstractTerraPlugin implements TerraPlugin { private final PluginConfigImpl config = new PluginConfigImpl(); - private final CommandManager manager = new TerraCommandManager(this); - private final AddonRegistry addonRegistry = new AddonRegistry(this); private final Lazy logger = Lazy.lazy(() -> createLogger()); @@ -186,12 +180,6 @@ public abstract class AbstractTerraPlugin implements TerraPlugin { } logger().info("Loaded addons."); - try { - CommandUtil.registerAll(manager); - } catch(MalformedCommandException e) { - e.printStackTrace(); // TODO do something here even though this should literally never happen - } - logger().info("Finished initialization."); } @@ -205,8 +193,4 @@ public abstract class AbstractTerraPlugin implements TerraPlugin { public ConfigRegistry getRawConfigRegistry() { return configRegistry; } - - public CommandManager getManager() { - return manager; - } } diff --git a/common/implementation/src/main/java/com/dfsek/terra/commands/TerraCommandManager.java b/common/implementation/src/main/java/com/dfsek/terra/commands/TerraCommandManager.java deleted file mode 100644 index 25dd87823..000000000 --- a/common/implementation/src/main/java/com/dfsek/terra/commands/TerraCommandManager.java +++ /dev/null @@ -1,294 +0,0 @@ -package com.dfsek.terra.commands; - -import net.jafama.FastMath; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.command.annotation.Switch; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.command.arg.ArgumentParser; -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.command.exception.ExecutionException; -import com.dfsek.terra.api.command.exception.InvalidArgumentsException; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.command.exception.SwitchFormatException; -import com.dfsek.terra.api.command.tab.TabCompleter; -import com.dfsek.terra.api.entity.CommandSender; -import com.dfsek.terra.api.entity.Player; -import com.dfsek.terra.api.injection.exception.InjectionException; -import com.dfsek.terra.api.util.reflection.ReflectionUtil; -import com.dfsek.terra.inject.InjectorImpl; - - -public class TerraCommandManager implements CommandManager { - private final Map commands = new HashMap<>(); - private final InjectorImpl pluginInjector; - private final TerraPlugin main; - - public TerraCommandManager(TerraPlugin main) { - this.main = main; - this.pluginInjector = new InjectorImpl<>(main); - pluginInjector.addExplicitTarget(TerraPlugin.class); - } - - @Override - public void execute(String commandName, CommandSender sender, List argsIn) throws CommandException { - if(!commands.containsKey(commandName)) throw new InvalidArgumentsException("No such command \"" + commandName + "\""); - execute(commands.get(commandName), sender, new ArrayList<>(argsIn)); - } - - @Override - public void register(String name, Class clazz) throws MalformedCommandException { - commands.put(name, new CommandHolder(clazz)); - } - - @Override - public List tabComplete(String command, CommandSender sender, List args) throws CommandException { - if(args.isEmpty()) return new ArrayList<>(commands.keySet()).stream().sorted(String::compareTo).collect(Collectors.toList()); - if(!commands.containsKey(command)) return Collections.emptyList(); - return tabComplete(commands.get(command), sender, new ArrayList<>(args)).stream().filter( - s -> s.toLowerCase().startsWith(args.get(args.size() - 1).toLowerCase())).sorted(String::compareTo).collect( - Collectors.toList()); - } - - @Override - public int getMaxArgumentDepth() { - int max = 0; - for(CommandHolder value : commands.values()) { - max = FastMath.max(getMaxArgumentDepth(value), max); - } - return max; - } - - private void execute(CommandHolder commandHolder, CommandSender sender, List args) throws CommandException { - Class commandClass = commandHolder.clazz; - - if(commandClass.isAnnotationPresent(DebugCommand.class) && !main.getTerraConfig().isDebugCommands()) { - sender.sendMessage("Command must be executed with debug commands enabled."); - return; - } - - if(commandClass.isAnnotationPresent(PlayerCommand.class) && !(sender instanceof Player)) { - sender.sendMessage("Command must be executed by player."); - return; - } - - if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player))) { - sender.sendMessage("Command must be executed in a Terra world."); - return; - } - - List ogArgs = new ArrayList<>(args); - - ExecutionState state = new ExecutionState(sender); - - if(!commandClass.isAnnotationPresent(Command.class)) { - invoke(commandClass, state, commandHolder); - return; - } - - Command command = commandClass.getAnnotation(Command.class); - - if(command.arguments().length == 0 && command.subcommands().length == 0) { - if(args.isEmpty()) { - invoke(commandClass, state, commandHolder); - return; - } else throw new InvalidArgumentsException("Expected 0 arguments, found " + args.size()); - } - - if(!args.isEmpty() && commandHolder.subcommands.containsKey(args.get(0))) { - String c = args.get(0); - args.remove(0); - execute(commandHolder.subcommands.get(c), sender, args); - return; - } - - boolean req = true; - for(Argument argument : command.arguments()) { - if(!req && argument.required()) { - throw new MalformedCommandException( - "Required arguments must come first! Arguments: " + Arrays.toString(command.arguments())); - } - req = argument.required(); - - if(args.isEmpty()) { - if(req) throw new InvalidArgumentsException("Invalid arguments: " + ogArgs + ", usage: " + command.usage()); - break; - } - - String arg = args.get(0); - - if(arg.startsWith("-")) { // switches have started. - if(req) throw new InvalidArgumentsException("Switches must come after arguments."); - break; - } - - state.addArgument(argument.value(), args.remove(0)); - } - - while(!args.isEmpty()) { - String aSwitch = args.remove(0); - if(!aSwitch.startsWith("-")) throw new SwitchFormatException("Invalid switch \"" + aSwitch + "\""); - - String val = aSwitch.substring(1); // remove dash - - if(!commandHolder.switches.containsKey(val)) throw new SwitchFormatException("No such switch \"" + aSwitch + "\""); - - state.addSwitch(commandHolder.switches.get(val)); - } - - invoke(commandClass, state, commandHolder); - } - - private void invoke(Class clazz, ExecutionState state, CommandHolder holder) throws CommandException { - try { - CommandTemplate template = clazz.getConstructor().newInstance(); - - pluginInjector.inject(template); - - for(Field field : ReflectionUtil.getFields(clazz)) { - if(field.isAnnotationPresent(ArgumentTarget.class)) { - ArgumentTarget argumentTarget = field.getAnnotation(ArgumentTarget.class); - if(!holder.argumentMap.containsKey(argumentTarget.value())) { - throw new MalformedCommandException( - "Argument Target specifies nonexistent argument \"" + argumentTarget.value() + "\""); - } - - String argument = argumentTarget.value(); - - ArgumentParser argumentParser = holder.argumentMap.get(argumentTarget.value()) - .argumentParser() - .getConstructor() - .newInstance(); - - pluginInjector.inject(argumentParser); - - field.setAccessible(true); - String value = state.getArgument(argument); - - if(value == null) value = holder.argumentMap.get(argumentTarget.value()).defaultValue(); - - field.set(template, argumentParser.parse(state.getSender(), value)); - } - if(field.isAnnotationPresent(SwitchTarget.class)) { - SwitchTarget switchTarget = field.getAnnotation(SwitchTarget.class); - if(!holder.switches.containsValue(switchTarget.value())) { - throw new MalformedCommandException("Switch Target specifies nonexistent switch \"" + switchTarget.value() + "\""); - } - - if(!(field.getType() == boolean.class)) { - throw new MalformedCommandException("Switch Target must be of type boolean."); - } - - field.setAccessible(true); - field.setBoolean(template, state.hasSwitch(switchTarget.value())); - } - } - - try { - template.execute(state.getSender()); - } catch(Throwable e) { - throw new ExecutionException("Failed to execute command: " + e.getMessage(), e); - } - } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) { - throw new MalformedCommandException("Unable to reflectively instantiate command: ", e); - } - } - - private List tabComplete(CommandHolder holder, CommandSender sender, List args) throws CommandException { - if(args.isEmpty()) return Collections.emptyList(); - List completions = new ArrayList<>(); - - if(args.size() == 1) { - completions.addAll(holder.subcommands.keySet()); - } - - if(holder.subcommands.containsKey(args.get(0))) { - List newArgs = new ArrayList<>(args); - newArgs.remove(0); - completions.addAll(tabComplete(holder.subcommands.get(args.get(0)), sender, newArgs)); - } - try { - if(args.size() <= holder.arguments.size()) { - TabCompleter completer = holder.arguments.get(args.size() - 1).tabCompleter().getConstructor().newInstance(); - pluginInjector.inject(completer); - completions.addAll(completer.complete(sender)); - } - } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) { - throw new MalformedCommandException("Unable to reflectively instantiate tab-completer: ", e); - } - return completions; - } - - private int getMaxArgumentDepth(CommandHolder holder) { - int max = 0; - max = FastMath.max(holder.arguments.size() + holder.switchList.size(), max); - for(CommandHolder value : holder.subcommands.values()) { - max = FastMath.max(max, getMaxArgumentDepth(value) + 1); - } - return max; - } - - - /** - * Pre-processes command metadata. - */ - private static final class CommandHolder { - private final Class clazz; - private final Map subcommands = new HashMap<>(); - private final Map switches = new HashMap<>(); - private final List arguments; - private final List switchList; - private final Map argumentMap = new HashMap<>(); - - private CommandHolder(Class clazz) throws MalformedCommandException { - this.clazz = clazz; - if(clazz.isAnnotationPresent(Command.class)) { - Command command = clazz.getAnnotation(Command.class); - for(Subcommand subcommand : command.subcommands()) { - if(subcommands.containsKey(subcommand.value())) - throw new MalformedCommandException("Duplicate subcommand: " + subcommand); - CommandHolder holder = new CommandHolder(subcommand.clazz()); - subcommands.put(subcommand.value(), holder); - for(String alias : subcommand.aliases()) { - subcommands.put(alias, holder); - } - } - for(Switch aSwitch : command.switches()) { - if(switches.containsKey(aSwitch.value())) throw new MalformedCommandException("Duplicate switch: " + aSwitch); - switches.put(aSwitch.value(), aSwitch.value()); - for(String alias : aSwitch.aliases()) { - switches.put(alias, aSwitch.value()); - } - } - for(Argument argument : command.arguments()) { - if(argumentMap.containsKey(argument.value())) throw new MalformedCommandException("Duplicate argument: " + argument); - argumentMap.put(argument.value(), argument); - } - arguments = Arrays.asList(command.arguments()); - switchList = Arrays.asList(command.switches()); - } else { - arguments = Collections.emptyList(); - switchList = Collections.emptyList(); - } - } - } -} diff --git a/common/implementation/src/test/java/command/CommandTest.java b/common/implementation/src/test/java/command/CommandTest.java deleted file mode 100644 index 670f1fbf9..000000000 --- a/common/implementation/src/test/java/command/CommandTest.java +++ /dev/null @@ -1,242 +0,0 @@ -package command; - -import org.junit.jupiter.api.Test; - -import java.util.Arrays; - -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.command.annotation.Switch; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; -import com.dfsek.terra.api.command.arg.DoubleArgumentParser; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.command.exception.InvalidArgumentsException; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.entity.CommandSender; -import com.dfsek.terra.commands.TerraCommandManager; - -import static org.junit.jupiter.api.Assertions.*; - - -public class CommandTest { - @Test - public void subcommand() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoParentCommand.class); - - manager.execute("test", null, Arrays.asList("subcommand1", "first", "2")); - manager.execute("test", null, Arrays.asList("subcommand2", "first", "2")); - manager.execute("test", null, Arrays.asList("s1", "first", "2", "3.4")); - manager.execute("test", null, Arrays.asList("s2", "first", "2")); - manager.execute("test", null, Arrays.asList("sub1", "first", "2", "3.4")); - manager.execute("test", null, Arrays.asList("sub2", "first", "2")); - manager.execute("test", null, Arrays.asList("first", "2")); // Parent command args - - System.out.println("ARGS: " + manager.getMaxArgumentDepth()); - } - - @Test - public void args() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoCommand.class); - - manager.execute("test", null, Arrays.asList("first", "2")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4")); - } - - @Test - public void argsBeforeFlags() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoCommand.class); - - try { - manager.execute("test", null, Arrays.asList("first", "-flag", "2")); - fail(); - } catch(InvalidArgumentsException ignore) { - } - } - - @Test - public void requiredArgsFirst() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoInvalidCommand.class); - - try { - manager.execute("test", null, Arrays.asList("first", "2")); - fail(); - } catch(MalformedCommandException ignore) { - } - } - - @Test - public void switches() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoSwitchCommand.class); - - manager.execute("test", null, Arrays.asList("first", "2")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4")); - - manager.execute("test", null, Arrays.asList("first", "2", "-a")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-b")); - - manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch")); - - manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch", "-b")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch", "-a")); - } - - @Command( - arguments = { - @Argument("arg0"), - @Argument(value = "arg1", argumentParser = IntegerArgumentParser.class), - @Argument(value = "arg2", required = false, argumentParser = DoubleArgumentParser.class, defaultValue = "0") - } - ) - public static final class DemoCommand implements CommandTemplate { - - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private Integer arg1; - - @ArgumentTarget("arg2") - private Double arg2; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - } - } - - - @Command( - arguments = { - @Argument("arg0"), - @Argument("arg1"), - @Argument(value = "arg2", required = false) - }, - switches = { - @Switch(value = "a", aliases = "aSwitch"), - @Switch(value = "b", aliases = "bSwitch") - } - ) - public static final class DemoSwitchCommand implements CommandTemplate { - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private String arg1; - - @ArgumentTarget("arg2") - private String arg2; - - @SwitchTarget("a") - private boolean a; - - @SwitchTarget("b") - private boolean b; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - - System.out.println("A: " + a); - System.out.println("B: " + b); - } - } - - - @Command( - arguments = { - @Argument("arg0"), - @Argument(value = "arg2", required = false), // optional arguments must be last. this command is invalid. - @Argument("arg1") - } - ) - public static final class DemoInvalidCommand implements CommandTemplate { - - @Override - public void execute(CommandSender sender) { - throw new Error("this should never be reached"); - } - } - - - @Command( - arguments = { - @Argument("arg0"), - @Argument("arg1"), - @Argument(value = "arg2", required = false), - }, - subcommands = { - @Subcommand( - value = "subcommand1", - aliases = { "s1", "sub1" }, - clazz = DemoChildCommand.class - ), - @Subcommand( - value = "subcommand2", - aliases = { "s2", "sub2" }, - clazz = DemoChildCommand.class // Duplicate command intentional. - ) - } - ) - public static final class DemoParentCommand implements CommandTemplate { - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private String arg1; - - @ArgumentTarget("arg2") - private String arg2; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - } - } - - - @Command( - arguments = { - @Argument("arg0"), - @Argument("arg1"), - @Argument(value = "arg2", required = false), - } - ) - public static final class DemoChildCommand implements CommandTemplate { - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private String arg1; - - @ArgumentTarget("arg2") - private String arg2; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java index cb6463e68..ff6546ff7 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -10,7 +10,6 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter; import io.papermc.lib.PaperLib; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; -import org.bukkit.command.PluginCommand; import org.bukkit.generator.ChunkGenerator; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -18,22 +17,14 @@ import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; -import java.util.Objects; -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.exception.MalformedCommandException; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; -import com.dfsek.terra.bukkit.command.BukkitCommandAdapter; -import com.dfsek.terra.bukkit.command.FixChunkCommand; -import com.dfsek.terra.bukkit.command.SaveDataCommand; import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; import com.dfsek.terra.bukkit.listeners.CommonListener; import com.dfsek.terra.bukkit.listeners.PaperListener; import com.dfsek.terra.bukkit.listeners.SpigotListener; import com.dfsek.terra.bukkit.util.PaperUtil; -import com.dfsek.terra.commands.CommandUtil; -import com.dfsek.terra.commands.TerraCommandManager; public class TerraBukkitPlugin extends JavaPlugin {