package me.lethunderhawk.minion.command; import me.lethunderhawk.bazaarflux.util.command.CommandNode; import me.lethunderhawk.bazaarflux.util.gui.InventoryManager; import me.lethunderhawk.clans.ClanModule; import me.lethunderhawk.minion.MinionModule; import me.lethunderhawk.minion.manager.MinionManager; import me.lethunderhawk.minion.ui.minionList.MinionLevelListMenu; import me.lethunderhawk.minion.ui.minionList.MinionListMenu; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.BiConsumer; import java.util.stream.Collectors; public class MinionCommand implements CommandExecutor, TabCompleter { private final CommandNode rootCommand; private final MinionModule module; public MinionCommand(MinionModule minionModule) { this.module = minionModule; this.rootCommand = new CommandNode("clan", "Main clan command", null); setupDefaultCommands(); } private void setupDefaultCommands() { registerCommand("all", "get all minions", this::getAll); registerCommand("reload", "reload", this::reload); registerCommand("removeAll", "remove all minions", this::removeAll); CommandNode menu = registerCommand("menu", "See all minion types in a GUI", this::showMenu); CommandNode cobble = new CommandNode("cobblestone", "See all cobblestone minions", this::showCobbleMenu); menu.addSubCommands(cobble); } private void showCobbleMenu(CommandSender sender, String[] strings) { if(sender instanceof Player p) { InventoryManager.openFor(p, new MinionLevelListMenu("cobblestone")); } } private void showMenu(CommandSender sender, String[] strings) { if(strings.length == 0 && sender instanceof Player p) { InventoryManager.openFor(p, new MinionListMenu()); } } private void removeAll(CommandSender sender, String[] strings) { MinionManager.stopAndUnregisterAll(); } private void reload(CommandSender sender, String[] strings) { module.reload(); } private void getAll(CommandSender sender, String[] strings) { if(!(sender instanceof Player p)) return; for(ItemStack minion : module.getAllMinions()){ p.getInventory().addItem(minion); } } // Helper method to easily register commands public CommandNode registerCommand(String name, String description, BiConsumer executor) { return rootCommand.registerSubCommand(name, description, executor); } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (args.length == 0) { sendHelp(sender); return true; } List argList = new ArrayList<>(Arrays.asList(args)); CommandNode currentNode = rootCommand; CommandNode targetNode = null; // Traverse the command tree while (!argList.isEmpty()) { String nextArg = argList.get(0); CommandNode nextNode = currentNode.getSubCommand(nextArg); if (nextNode == null) { // No matching subcommand found, use current node if it has an executor targetNode = currentNode.getExecutor() != null ? currentNode : null; break; } currentNode = nextNode; argList.remove(0); // If this is the last argument or node has no further subcommands if (argList.isEmpty() || nextNode.getSubCommands().isEmpty()) { targetNode = nextNode; break; } } if (targetNode == null) { ClanModule.sendText(sender,"§cUnknown command. Use /minion help for available commands."); return true; } if (targetNode.getExecutor() == null) { ClanModule.sendText(sender,"§cThis command requires additional arguments."); sendSubCommands(sender, targetNode); return true; } // Execute the command with remaining arguments String[] remainingArgs = argList.toArray(new String[0]); targetNode.getExecutor().accept(sender, remainingArgs); return true; } @Override public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { List suggestions = new ArrayList<>(); if (args.length == 0) { return suggestions; } // Start at root and traverse CommandNode currentNode = rootCommand; List argList = new ArrayList<>(Arrays.asList(args)); String lastArg = args[args.length - 1].toLowerCase(); // Try to traverse as far as possible for (int i = 0; i < argList.size() - 1; i++) { String arg = argList.get(i); CommandNode nextNode = currentNode.getSubCommand(arg); if (nextNode == null) { break; } currentNode = nextNode; } // Get suggestions from current node if (currentNode.getTabCompleter() != null) { suggestions.addAll(currentNode.getTabCompleter().apply(sender, args)); } else { // Suggest subcommands suggestions.addAll(currentNode.getSubCommandNames().stream() .filter(name -> name.toLowerCase().startsWith(lastArg)) .collect(Collectors.toList())); } return suggestions; } private void sendHelp(CommandSender sender) { sender.sendMessage("§6=== Minion Commands ==="); for (CommandNode cmd : rootCommand.getSubCommands()) { sender.sendMessage("§e/minion " + cmd.getName() + " §7- " + cmd.getDescription()); } } private void sendSubCommands(CommandSender sender, CommandNode node) { sender.sendMessage("§6Available subcommands:"); for (CommandNode subCmd : node.getSubCommands()) { sender.sendMessage("§e" + subCmd.getName() + " §7- " + subCmd.getDescription()); } } }