package net.knarcraft.stargate.command; import net.knarcraft.stargate.config.ConfigOption; import net.knarcraft.stargate.config.OptionDataType; import net.md_5.bungee.api.ChatColor; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; /** * This is the completer for stargates config sub-command (/sg config) */ public class ConfigTabCompleter implements TabCompleter { private List signTypes; private List booleans; private List numbers; private List chatColors; private List languages; private List extendedColors; @Nullable @Override public List onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { if (signTypes == null || booleans == null || numbers == null || chatColors == null || languages == null) { initializeAutoCompleteLists(); } if (args.length > 1) { ConfigOption selectedOption = ConfigOption.getByName(args[0]); if (selectedOption == null) { return new ArrayList<>(); } else if (selectedOption.getDataType() == OptionDataType.STRING_LIST) { return getPossibleStringListOptionValues(selectedOption, args); } else { return getPossibleOptionValues(selectedOption, args[1]); } } else { List configOptionNames = new ArrayList<>(); for (ConfigOption option : ConfigOption.values()) { configOptionNames.add(option.getName()); } return filterMatching(configOptionNames, args[0]); } } /** * Find completable strings which match the text typed by the command's sender * * @param values

The values to filter

* @param typedText

The text the player has started typing

* @return

The given string values which start with the player's typed text

*/ private List filterMatching(List values, String typedText) { List configValues = new ArrayList<>(); for (String value : values) { if (value.toLowerCase().startsWith(typedText.toLowerCase())) { configValues.add(value); } } return configValues; } /** * Get possible values for the selected option * * @param selectedOption

The selected option

* @param typedText

The beginning of the typed text, for filtering matching results

* @return

Some or all of the valid values for the option

*/ private List getPossibleOptionValues(ConfigOption selectedOption, String typedText) { switch (selectedOption) { case LANGUAGE: //Return available languages return filterMatching(languages, typedText); case GATE_FOLDER: case PORTAL_FOLDER: case DEFAULT_GATE_NETWORK: //Just return the default value as most values should be possible if (typedText.trim().isEmpty()) { return putStringInList((String) selectedOption.getDefaultValue()); } else { return new ArrayList<>(); } case MAIN_SIGN_COLOR: case HIGHLIGHT_SIGN_COLOR: case FREE_GATES_COLOR: //Return all colors return filterMatching(chatColors, typedText); } //If the config value is a boolean, show the two boolean values if (selectedOption.getDataType() == OptionDataType.BOOLEAN) { return filterMatching(booleans, typedText); } //If the config value is an integer, display some valid numbers if (selectedOption.getDataType() == OptionDataType.INTEGER) { if (typedText.trim().isEmpty()) { return numbers; } else { return new ArrayList<>(); } } return null; } /** * Get possible values for the selected string list option * * @param selectedOption

The selected option

* @param args

The arguments given by the user

* @return

Some or all of the valid values for the option

*/ private List getPossibleStringListOptionValues(ConfigOption selectedOption, String[] args) { if (selectedOption == ConfigOption.PER_SIGN_COLORS) { return getPerSignColorCompletion(args); } else { return null; } } /** * Gets the tab completion values for completing the per-sign color text * * @param args

The arguments given by the user

* @return

The options to give the user

*/ private List getPerSignColorCompletion(String[] args) { if (args.length < 3) { return filterMatching(signTypes, args[1]); } else if (args.length < 4) { return filterMatching(extendedColors, args[2]); } else if (args.length < 5) { return filterMatching(extendedColors, args[3]); } return new ArrayList<>(); } /** * Puts a single string value into a string list * * @param value

The string to make into a list

* @return

A list containing the string value

*/ private List putStringInList(String value) { List list = new ArrayList<>(); list.add(value); return list; } /** * Initializes all lists of auto-completable values */ private void initializeAutoCompleteLists() { booleans = new ArrayList<>(); booleans.add("true"); booleans.add("false"); numbers = new ArrayList<>(); numbers.add("0"); numbers.add("5"); signTypes = new ArrayList<>(); for (Material material : Material.values()) { if (Tag.STANDING_SIGNS.isTagged(material)) { signTypes.add(material.toString().replace("_SIGN", "")); } } getColors(); initializeLanguages(); extendedColors = new ArrayList<>(chatColors); extendedColors.add("default"); extendedColors.add("inverted"); } /** * Initializes the list of chat colors */ private void getColors() { chatColors = new ArrayList<>(); for (ChatColor color : getChatColors()) { chatColors.add(color.getName()); } } /** * Gets available chat colors * * @return

The available chat colors

*/ private List getChatColors() { List chatColors = new ArrayList<>(); chatColors.add(ChatColor.WHITE); chatColors.add(ChatColor.BLUE); chatColors.add(ChatColor.DARK_BLUE); chatColors.add(ChatColor.DARK_PURPLE); chatColors.add(ChatColor.LIGHT_PURPLE); chatColors.add(ChatColor.GOLD); chatColors.add(ChatColor.GREEN); chatColors.add(ChatColor.BLACK); chatColors.add(ChatColor.DARK_GREEN); chatColors.add(ChatColor.DARK_RED); chatColors.add(ChatColor.RED); chatColors.add(ChatColor.AQUA); chatColors.add(ChatColor.DARK_AQUA); chatColors.add(ChatColor.DARK_GRAY); chatColors.add(ChatColor.GRAY); chatColors.add(ChatColor.YELLOW); chatColors.add(ChatColor.of("#ed76d9")); chatColors.add(ChatColor.of("#ffecb7")); return chatColors; } /** * Initializes the list of all available languages */ private void initializeLanguages() { languages = new ArrayList<>(); languages.add("de"); languages.add("en"); languages.add("es"); languages.add("fr"); languages.add("hu"); languages.add("it"); languages.add("nb-no"); languages.add("nl"); languages.add("nn-no"); languages.add("pt-br"); languages.add("ru"); //TODO: Generate this list dynamically by listing the language files in the jar and adding the user's custom // language files } }