package nl.sugcube.crystalquest.command; import nl.sugcube.crystalquest.Broadcast; import nl.sugcube.crystalquest.CrystalQuest; import org.bukkit.command.CommandSender; import java.util.*; /** * A crystal quest command is a subcommand of the /cq command. Confusing? Don't think so. * <p> * For example "spectate [arenas]" is a CrystalQuest command. * * @author SugarCaney */ public abstract class CrystalQuestCommand { /** * The name of the command as it appears after the `/cq` command. */ protected final String name; /** * The node in the language file that displays the usage message. */ protected final String usageNode; /** * The minimum amount of arguments that are expected for the command. */ protected final int argumentCount; /** * Permissions required to issue the command. * <p> * Only one of the permissions in this list is required in order to be allowed to execute the * command. When the set is empty, it means that everyone is allowed to execute the command. */ protected final Set<String> permissions; /** * Contains what type of content must be auto completed at what index of the command. * <p> * Maps the index of the argument (NOT including the command name itself) to the type of * stuff that needs to be autocompleted. This map only contains arguments that must be auto * completed. */ protected final Map<Integer, AutoCompleteArgument> autoCompleteMeta; /** * @param name * The name of the command after `/cq` * @param usageNode * The node of the usage-message in the language file. * @param argumentCount * The amount of arguments are expected for the command. */ public CrystalQuestCommand(String name, String usageNode, int argumentCount) { this.name = name; this.usageNode = usageNode; this.argumentCount = argumentCount; this.permissions = new HashSet<>(); this.autoCompleteMeta = new HashMap<>(); } /** * Executes the given command. * * @param plugin * The main CrystalQuest plugin instance. * @param sender * The one who executed the command. * @param arguments * The arguments that appear after `/cq {@code name}`. */ public final void execute(CrystalQuest plugin, CommandSender sender, String... arguments) { // Check permissions. if (!hasPermission(sender)) { sender.sendMessage(Broadcast.NO_PERMISSION); return; } // Check sender. if (!assertSender(sender)) { sender.sendMessage(Broadcast.ONLY_IN_GAME); return; } // Check argument count. if (arguments.length < argumentCount) { sender.sendMessage(Broadcast.get(usageNode)); return; } // Execute command executeImpl(plugin, sender, arguments); } /** * Get what type must be autocompleted at the given index. * * @param index * The argument index. */ public Optional<AutoCompleteArgument> getAutoComplete(int index) { return Optional.ofNullable(autoCompleteMeta.get(index)); } /** * Get the name of the command i.e. what is typed after `\cq`. */ public String getName() { return name; } /** * Implementation of the command execution. * * @param plugin * The main CrystalQuest plugin instance. * @param sender * The one who executed the command. * @param arguments * The arguments that appear after `/cq {@code name}`. */ protected abstract void executeImpl(CrystalQuest plugin, CommandSender sender, String... arguments); /** * Checks whether the given CommandSender may execute the command or not. * * @return Whether the command sender may execute the command or not. */ abstract protected boolean assertSender(CommandSender sender); /** * Adds the given permissions to the command. * * @see CrystalQuestCommand#permissions */ protected void addPermissions(String... permissions) { Collections.addAll(this.permissions, permissions); } /** * Checks whether the given sender has enough permissions to execute the command. * * @return Whether the sender has enough permissions to execute the command. */ protected boolean hasPermission(CommandSender sender) { if (permissions.isEmpty()) { return true; } for (String permission : permissions) { if (sender.hasPermission(permission)) { return true; } } return false; } /** * @see CrystalQuestCommand#autoCompleteMeta */ protected void addAutoCompleteMeta(int index, AutoCompleteArgument argumentType) { autoCompleteMeta.put(index, argumentType); } }