package me.rigamortis.seppuku.impl.management; import me.rigamortis.seppuku.Seppuku; import me.rigamortis.seppuku.api.command.Command; import me.rigamortis.seppuku.api.event.command.EventCommandLoad; import me.rigamortis.seppuku.api.module.Module; import me.rigamortis.seppuku.api.util.ReflectionUtil; import me.rigamortis.seppuku.api.util.StringUtil; import me.rigamortis.seppuku.api.value.Regex; import me.rigamortis.seppuku.api.value.Shader; import me.rigamortis.seppuku.api.value.Value; import me.rigamortis.seppuku.impl.command.*; import me.rigamortis.seppuku.impl.config.ModuleConfig; import net.minecraft.util.text.TextComponentString; import java.io.File; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.logging.Level; /** * Author Seth * 4/16/2019 @ 8:36 AM. */ public final class CommandManager { private List commandList = new ArrayList<>(); public CommandManager() { this.commandList.add(new HelpCommand()); this.commandList.add(new ToggleCommand()); this.commandList.add(new VClipCommand()); this.commandList.add(new HClipCommand()); this.commandList.add(new HideCommand()); this.commandList.add(new ColorCommand()); this.commandList.add(new BindCommand()); this.commandList.add(new XrayCommand()); this.commandList.add(new FriendCommand()); this.commandList.add(new PeekCommand()); this.commandList.add(new SpectateCommand()); this.commandList.add(new ModuleCommand()); this.commandList.add(new YawCommand()); this.commandList.add(new PitchCommand()); this.commandList.add(new NameCommand()); this.commandList.add(new MacroCommand()); this.commandList.add(new WaypointsCommand()); this.commandList.add(new ReloadCommand()); this.commandList.add(new UnloadCommand()); this.commandList.add(new DupeCommand()); this.commandList.add(new InvSeeCommand()); this.commandList.add(new SayCommand()); this.commandList.add(new IPCommand()); this.commandList.add(new CoordsCommand()); this.commandList.add(new ConnectCommand()); this.commandList.add(new DisconnectCommand()); this.commandList.add(new SeedCommand()); this.commandList.add(new TeleportCommand()); this.commandList.add(new IgnoreCommand()); this.commandList.add(new AutoIgnoreCommand()); this.commandList.add(new JavaScriptCommand()); this.commandList.add(new FakeChatCommand()); this.commandList.add(new EnchantCommand()); this.commandList.add(new RenameCommand()); this.commandList.add(new RenameModuleCommand()); this.commandList.add(new SpawnEggCommand()); this.commandList.add(new StackSizeCommand()); this.commandList.add(new CrashSlimeCommand()); this.commandList.add(new SignBookCommand()); this.commandList.add(new SkullCommand()); this.commandList.add(new GiveCommand()); this.commandList.add(new CalcStrongholdCommand()); this.commandList.add(new LastInvCommand()); this.commandList.add(new SearchCommand()); this.commandList.add(new PlayCommand()); this.commandList.add(new LocateFeatureCommand()); this.commandList.add(new MainMenuCommand()); this.commandList.add(new ConfigCommand()); this.commandList.add(new NukerFilterCommand()); //create commands for every value within every module loadValueCommands(); //load our external commands loadExternalCommands(); commandList.sort(Comparator.comparing(Command::getDisplayName)); } /** * This is where we load custom external commands from disk * This allows users to create their own commands and load * them during runtime */ public void loadExternalCommands() { try { //create a directory at "Seppuku/Commands" final File dir = new File("Seppuku/Commands"); //if it doesnt exist create it if (!dir.exists()) { dir.mkdirs(); } //all jars/zip files in the dir //loop though all classes within the jar/zip for (Class clazz : ReflectionUtil.getClassesEx(dir.getPath())) { if (clazz != null) { //if we have found a class and the class inherits "Module" if (Command.class.isAssignableFrom(clazz)) { //create a new instance of the class final Command command = (Command) clazz.newInstance(); //add the class to our list of modules this.commandList.add(command); Seppuku.INSTANCE.getEventManager().dispatchEvent(new EventCommandLoad(command)); Seppuku.INSTANCE.getLogger().log(Level.INFO, "Found external command " + command.getDisplayName()); } } } } catch (Exception e) { e.printStackTrace(); } } public void loadValueCommands() { for (final Module module : Seppuku.INSTANCE.getModuleManager().getModuleList()) { if (module.getValueList().size() > 0) { this.commandList.add(new Command(module.getDisplayName(), module.getAlias(), module.getDesc() != null ? module.getDesc() : "There is no description for this command", module.toUsageTextComponent()) { @Override public TextComponentString getTextComponentUsage() { return module.toUsageTextComponent(); } @Override public void exec(String input) { if (!this.clamp(input, 2, 3)) { this.printUsage(); return; } final String[] split = input.split(" "); final Value v = module.findValue(split[1]); if (v != null) { if (v.getValue() instanceof Boolean) { if (split.length == 3) { if (split[2].equalsIgnoreCase("true") || split[2].equalsIgnoreCase("false") || split[2].equalsIgnoreCase("1") || split[2].equalsIgnoreCase("0")) { if (split[2].equalsIgnoreCase("1")) { v.setValue(true); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to \247atrue"); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } else if (split[2].equalsIgnoreCase("0")) { v.setValue(false); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to \247cfalse"); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } else { v.setValue(Boolean.parseBoolean(split[2])); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to " + ((Boolean) v.getValue() ? "\247a" : "\247c") + v.getValue()); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } } else { Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[2] + "\" expected true/false"); } } else { v.setValue(!((Boolean) v.getValue())); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to " + ((Boolean) v.getValue() ? "\247a" : "\247c") + v.getValue()); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } } if (v.getValue() instanceof String) { if (!this.clamp(input, 3, 3)) { this.printUsage(); return; } v.setValue(split[2]); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to " + split[2]); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } if (v.getValue() instanceof Number && !(v.getValue() instanceof Enum)) { if (!this.clamp(input, 3, 3)) { this.printUsage(); return; } if (v.getValue().getClass() == Float.class) { if (StringUtil.isFloat(split[2])) { v.setValue(Float.parseFloat(split[2])); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to \247b" + Float.parseFloat(split[2])); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } else { Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[2] + "\" expected a number"); } } if (v.getValue().getClass() == Double.class) { if (StringUtil.isDouble(split[2])) { v.setValue(Double.parseDouble(split[2])); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to \247b" + Double.parseDouble(split[2])); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } else { Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[2] + "\" expected a number"); } } if (v.getValue().getClass() == Integer.class) { if (StringUtil.isInt(split[2])) { v.setValue(Integer.parseInt(split[2])); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to \247b" + Integer.parseInt(split[2])); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } else { Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[2] + "\" expected a number"); } } } if (v.getValue() instanceof Enum) { if (!this.clamp(input, 3, 3) || split[2].matches("-?\\d+(\\.\\d+)?")) { // is a number? this.printUsage(); return; } final int op = v.getEnum(split[2]); if (op != -1) { v.setEnumValue(split[2]); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to \247e" + ((Enum) v.getValue()).name().toLowerCase()); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } else { Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[2] + "\" expected a string"); } } if (v.getValue() instanceof Regex) { if (!this.clamp(input, 2, 3)) { this.printUsage(); return; } final Regex regex = (Regex) v.getValue(); if (split.length == 2 || split[2].equals("")) { regex.setPatternString(""); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f cleared"); } else { final String oldPatternString = regex.getPatternString(); regex.setPatternString(split[2]); if (regex.getPattern() == null) { regex.setPatternString(oldPatternString); Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[2] + "\" expected a valid regular expression or an empty string"); } else { Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to " + split[2]); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } } } if (v.getValue() instanceof Shader) { if (!this.clamp(input, 2, 3)) { this.printUsage(); return; } final Shader shader = (Shader) v.getValue(); if (split.length == 2 || split[2].equals("")) { shader.setShaderID(""); Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f unset"); } else { final String oldShaderID = shader.getShaderID(); shader.setShaderID(split[2]); if (shader.getShaderProgram() == null) { shader.setShaderID(oldShaderID); Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[2] + "\" expected an existing shader ID or an empty string"); } else { Seppuku.INSTANCE.logChat(module.getDisplayName() + " \2477" + v.getName() + "\247f set to " + split[2]); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); } } } } else { Seppuku.INSTANCE.errorChat("Invalid input " + "\"" + split[1] + "\""); this.printUsage(); } } }); } } } /** * Returns a given command based on display name or alias * * @param alias * @return */ public Command find(String alias) { for (Command cmd : this.getCommandList()) { for (String s : cmd.getAlias()) { if (alias.equalsIgnoreCase(s) || alias.equalsIgnoreCase(cmd.getDisplayName())) { return cmd; } } } return null; } /** * Returns the most similar command based on display name or alias * * @param input * @return */ public Command findSimilar(String input) { Command cmd = null; double similarity = 0.0f; for (Command command : this.getCommandList()) { final double currentSimilarity = StringUtil.levenshteinDistance(input, command.getDisplayName()); if (currentSimilarity >= similarity) { similarity = currentSimilarity; cmd = command; } } return cmd; } public void unload() { for (Command cmd : this.commandList) { Seppuku.INSTANCE.getEventManager().removeEventListener(cmd); } this.commandList.clear(); } public List getCommandList() { return commandList; } public void setCommandList(List commandList) { this.commandList = commandList; } }