diff --git a/src/main/java/dansplugins/mailboxes/Mailboxes.java b/src/main/java/dansplugins/mailboxes/Mailboxes.java index 4bacb31..503fada 100644 --- a/src/main/java/dansplugins/mailboxes/Mailboxes.java +++ b/src/main/java/dansplugins/mailboxes/Mailboxes.java @@ -1,6 +1,7 @@ package dansplugins.mailboxes; import dansplugins.mailboxes.bstats.Metrics; +import dansplugins.mailboxes.commands.*; import dansplugins.mailboxes.data.PersistentData; import dansplugins.mailboxes.externalapi.MailboxesAPI; import dansplugins.mailboxes.factories.MailboxFactory; @@ -13,6 +14,9 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; public final class Mailboxes extends JavaPlugin { private final String pluginVersion = "v" + getDescription().getVersion(); @@ -82,4 +86,79 @@ public MailboxesAPI getAPI() { private boolean isVersionMismatched() { return !getConfig().getString("version").equalsIgnoreCase(getVersion()); } + + @Override + public List onTabComplete(CommandSender sender, Command cmd, String label, String[] args) { + if (label.equalsIgnoreCase("mailboxes") || label.equalsIgnoreCase("m")) { + return getTabCompletions(sender, args); + } + return null; + } + + private List getTabCompletions(CommandSender sender, String[] args) { + if (args.length == 1) { + // Main subcommands - filter by permissions + List subcommands = new ArrayList<>(); + if (sender.hasPermission("mailboxes.help")) subcommands.add("help"); + if (sender.hasPermission("mailboxes.config")) subcommands.add("config"); + if (sender.hasPermission("mailboxes.list")) subcommands.add("list"); + if (sender.hasPermission("mailboxes.send")) subcommands.add("send"); + if (sender.hasPermission("mailboxes.open")) subcommands.add("open"); + if (sender.hasPermission("mailboxes.delete")) subcommands.add("delete"); + if (sender.hasPermission("mailboxes.archive")) subcommands.add("archive"); + return filterCompletions(subcommands, args[0]); + } + + if (args.length >= 2) { + String subcommand = args[0].toLowerCase(); + + switch (subcommand) { + case "config": + if (sender.hasPermission("mailboxes.config")) { + ConfigCommand configCommand = new ConfigCommand(configService); + return configCommand.getTabCompletions(args); + } + break; + case "list": + if (sender.hasPermission("mailboxes.list")) { + ListCommand listCommand = new ListCommand(logger, persistentData); + return listCommand.getTabCompletions(args); + } + break; + case "send": + if (sender.hasPermission("mailboxes.send")) { + SendCommand sendCommand = new SendCommand(logger, uuidChecker, configService, argumentParser, messageFactory, mailService); + return sendCommand.getTabCompletions(sender, args); + } + break; + case "open": + if (sender.hasPermission("mailboxes.open")) { + OpenCommand openCommand = new OpenCommand(logger, persistentData); + return openCommand.getTabCompletions(sender, args); + } + break; + case "delete": + if (sender.hasPermission("mailboxes.delete")) { + DeleteCommand deleteCommand = new DeleteCommand(persistentData); + return deleteCommand.getTabCompletions(sender, args); + } + break; + case "archive": + if (sender.hasPermission("mailboxes.archive")) { + ArchiveCommand archiveCommand = new ArchiveCommand(persistentData); + return archiveCommand.getTabCompletions(sender, args); + } + break; + } + } + + return new ArrayList<>(); + } + + private List filterCompletions(List options, String input) { + String lowerInput = input.toLowerCase(); + return options.stream() + .filter(option -> option.toLowerCase().startsWith(lowerInput)) + .collect(Collectors.toList()); + } } \ No newline at end of file diff --git a/src/main/java/dansplugins/mailboxes/commands/ArchiveCommand.java b/src/main/java/dansplugins/mailboxes/commands/ArchiveCommand.java index a9c7d96..86a394c 100644 --- a/src/main/java/dansplugins/mailboxes/commands/ArchiveCommand.java +++ b/src/main/java/dansplugins/mailboxes/commands/ArchiveCommand.java @@ -7,6 +7,12 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + public class ArchiveCommand { private final PersistentData persistentData; @@ -53,4 +59,31 @@ public boolean execute(CommandSender sender, String[] args) { return true; } + public List getTabCompletions(CommandSender sender, String[] args) { + if (args.length == 2 && sender instanceof Player) { + Player player = (Player) sender; + Mailbox mailbox = persistentData.getMailbox(player); + + if (mailbox != null) { + // Use Set to avoid duplicates (though unlikely based on design) + Set messageIds = new HashSet<>(); + + // Add active message IDs (only active messages can be archived) + for (Message message : mailbox.getActiveMessages()) { + messageIds.add(String.valueOf(message.getID())); + } + + return filterCompletions(new ArrayList<>(messageIds), args[1]); + } + } + return new ArrayList<>(); + } + + private List filterCompletions(List options, String input) { + String lowerInput = input.toLowerCase(); + return options.stream() + .filter(option -> option.toLowerCase().startsWith(lowerInput)) + .collect(Collectors.toList()); + } + } diff --git a/src/main/java/dansplugins/mailboxes/commands/ConfigCommand.java b/src/main/java/dansplugins/mailboxes/commands/ConfigCommand.java index 4e9d694..c1f1304 100644 --- a/src/main/java/dansplugins/mailboxes/commands/ConfigCommand.java +++ b/src/main/java/dansplugins/mailboxes/commands/ConfigCommand.java @@ -4,9 +4,43 @@ import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + public class ConfigCommand { private final ConfigService configService; + // Config option names for tab completion (in camelCase to match config file) + // Note: 'version' is intentionally excluded as it cannot be set by users + private static final List CONFIG_OPTIONS = Arrays.asList( + "debugMode", + "maxMessageIDNumber", + "maxMailboxIDNumber", + "preventSendingMessagesToSelf", + "assignmentAlertEnabled", + "unreadMessagesAlertEnabled", + "welcomeMessageEnabled", + "quotesEnabled", + "attachmentsEnabled", + "maxAttachmentStackSize" + ); + + // Boolean config options (stored in lowercase for case-insensitive comparison) + // These are derived from CONFIG_OPTIONS to maintain consistency + private static final Set BOOLEAN_CONFIG_OPTIONS = new HashSet<>(Arrays.asList( + "debugmode", + "preventsendingmessagestoself", + "assignmentalertenabled", + "unreadmessagesalertenabled", + "welcomemessageenabled", + "quotesenabled", + "attachmentsenabled" + )); + public ConfigCommand(ConfigService configService) { this.configService = configService; } @@ -39,4 +73,30 @@ else if (args[0].equalsIgnoreCase("set")) { } } + public List getTabCompletions(String[] args) { + if (args.length == 2) { + // Config subcommands + return filterCompletions(Arrays.asList("show", "set"), args[1]); + } + if (args.length == 3 && args[1].equalsIgnoreCase("set")) { + // Config options + return filterCompletions(CONFIG_OPTIONS, args[2]); + } + if (args.length == 4 && args[1].equalsIgnoreCase("set")) { + // Suggest values based on the config option type + String option = args[2]; + if (BOOLEAN_CONFIG_OPTIONS.contains(option.toLowerCase())) { + return filterCompletions(Arrays.asList("true", "false"), args[3]); + } + } + return new ArrayList<>(); + } + + private List filterCompletions(List options, String input) { + String lowerInput = input.toLowerCase(); + return options.stream() + .filter(option -> option.toLowerCase().startsWith(lowerInput)) + .collect(Collectors.toList()); + } + } diff --git a/src/main/java/dansplugins/mailboxes/commands/DeleteCommand.java b/src/main/java/dansplugins/mailboxes/commands/DeleteCommand.java index dcd7e50..04595c9 100644 --- a/src/main/java/dansplugins/mailboxes/commands/DeleteCommand.java +++ b/src/main/java/dansplugins/mailboxes/commands/DeleteCommand.java @@ -7,6 +7,12 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + public class DeleteCommand { private final PersistentData persistentData; @@ -48,4 +54,36 @@ public boolean execute(CommandSender sender, String[] args) { return true; } + public List getTabCompletions(CommandSender sender, String[] args) { + if (args.length == 2 && sender instanceof Player) { + Player player = (Player) sender; + Mailbox mailbox = persistentData.getMailbox(player); + + if (mailbox != null) { + // Use Set to avoid duplicates (though unlikely based on design) + Set messageIds = new HashSet<>(); + + // Add active message IDs + for (Message message : mailbox.getActiveMessages()) { + messageIds.add(String.valueOf(message.getID())); + } + + // Add archived message IDs + for (Message message : mailbox.getArchivedMessages()) { + messageIds.add(String.valueOf(message.getID())); + } + + return filterCompletions(new ArrayList<>(messageIds), args[1]); + } + } + return new ArrayList<>(); + } + + private List filterCompletions(List options, String input) { + String lowerInput = input.toLowerCase(); + return options.stream() + .filter(option -> option.toLowerCase().startsWith(lowerInput)) + .collect(Collectors.toList()); + } + } diff --git a/src/main/java/dansplugins/mailboxes/commands/ListCommand.java b/src/main/java/dansplugins/mailboxes/commands/ListCommand.java index daf5a39..f1a09ea 100644 --- a/src/main/java/dansplugins/mailboxes/commands/ListCommand.java +++ b/src/main/java/dansplugins/mailboxes/commands/ListCommand.java @@ -7,6 +7,11 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + public class ListCommand { private final Logger logger; private final PersistentData persistentData; @@ -53,4 +58,18 @@ else if (list.equalsIgnoreCase("unread")) { return true; } + public List getTabCompletions(String[] args) { + if (args.length == 2) { + return filterCompletions(Arrays.asList("active", "archived", "unread"), args[1]); + } + return new ArrayList<>(); + } + + private List filterCompletions(List options, String input) { + String lowerInput = input.toLowerCase(); + return options.stream() + .filter(option -> option.toLowerCase().startsWith(lowerInput)) + .collect(Collectors.toList()); + } + } diff --git a/src/main/java/dansplugins/mailboxes/commands/OpenCommand.java b/src/main/java/dansplugins/mailboxes/commands/OpenCommand.java index dacb897..6cab19e 100644 --- a/src/main/java/dansplugins/mailboxes/commands/OpenCommand.java +++ b/src/main/java/dansplugins/mailboxes/commands/OpenCommand.java @@ -11,7 +11,10 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; public class OpenCommand { private final Logger logger; @@ -77,4 +80,36 @@ public boolean execute(CommandSender sender, String[] args) { return true; } + public List getTabCompletions(CommandSender sender, String[] args) { + if (args.length == 2 && sender instanceof Player) { + Player player = (Player) sender; + Mailbox mailbox = persistentData.getMailbox(player); + + if (mailbox != null) { + // Use Set to avoid duplicates (though unlikely based on design) + Set messageIds = new HashSet<>(); + + // Add active message IDs + for (Message message : mailbox.getActiveMessages()) { + messageIds.add(String.valueOf(message.getID())); + } + + // Add archived message IDs + for (Message message : mailbox.getArchivedMessages()) { + messageIds.add(String.valueOf(message.getID())); + } + + return filterCompletions(new ArrayList<>(messageIds), args[1]); + } + } + return new ArrayList<>(); + } + + private List filterCompletions(List options, String input) { + String lowerInput = input.toLowerCase(); + return options.stream() + .filter(option -> option.toLowerCase().startsWith(lowerInput)) + .collect(Collectors.toList()); + } + } diff --git a/src/main/java/dansplugins/mailboxes/commands/SendCommand.java b/src/main/java/dansplugins/mailboxes/commands/SendCommand.java index 59a7fe9..1736ea2 100644 --- a/src/main/java/dansplugins/mailboxes/commands/SendCommand.java +++ b/src/main/java/dansplugins/mailboxes/commands/SendCommand.java @@ -7,14 +7,21 @@ import dansplugins.mailboxes.utils.ArgumentParser; import dansplugins.mailboxes.utils.Logger; import dansplugins.mailboxes.utils.UUIDChecker; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; public class SendCommand { private final Logger logger; @@ -123,4 +130,47 @@ public boolean execute(CommandSender sender, String[] args) { return true; } + public List getTabCompletions(CommandSender sender, String[] args) { + if (args.length == 2) { + // Player names (both online and offline) only at position 2 + // Use Set to avoid duplicates (online players also appear in offline list) + Set playerNames = new HashSet<>(); + + // Add online players + for (Player player : Bukkit.getOnlinePlayers()) { + playerNames.add(player.getName()); + } + + // Add offline players (online players will be deduplicated by Set) + for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { + if (player.getName() != null) { + playerNames.add(player.getName()); + } + } + + return filterCompletions(new ArrayList<>(playerNames), args[1]); + } + // Suggest -attach flag for subsequent positions if not already present + if (args.length >= 3) { + return getAttachFlagSuggestion(sender, args, args[args.length - 1]); + } + return new ArrayList<>(); + } + + private List getAttachFlagSuggestion(CommandSender sender, String[] args, String input) { + // Check if -attach flag is already present + boolean hasAttachFlag = Arrays.stream(args).anyMatch(arg -> arg.equalsIgnoreCase("-attach")); + if (!hasAttachFlag && sender.hasPermission("mailboxes.send.attach")) { + return filterCompletions(Arrays.asList("-attach"), input); + } + return new ArrayList<>(); + } + + private List filterCompletions(List options, String input) { + String lowerInput = input.toLowerCase(); + return options.stream() + .filter(option -> option.toLowerCase().startsWith(lowerInput)) + .collect(Collectors.toList()); + } + }