|
@@ -0,0 +1,378 @@
|
|
|
|
|
+package me.lethunderhawk.clans.command;
|
|
|
|
|
+
|
|
|
|
|
+import me.lethunderhawk.bazaarflux.util.command.CommandNode;
|
|
|
|
|
+import me.lethunderhawk.clans.Clan;
|
|
|
|
|
+import me.lethunderhawk.clans.ClanManager;
|
|
|
|
|
+import me.lethunderhawk.clans.ClanModule;
|
|
|
|
|
+import me.lethunderhawk.clans.claim.Claim;
|
|
|
|
|
+import me.lethunderhawk.clans.gui.ClanGUI;
|
|
|
|
|
+import me.lethunderhawk.clans.rules.Rule;
|
|
|
|
|
+import me.lethunderhawk.main.Main;
|
|
|
|
|
+import net.kyori.adventure.text.Component;
|
|
|
|
|
+import net.kyori.adventure.text.format.NamedTextColor;
|
|
|
|
|
+import org.bukkit.Bukkit;
|
|
|
|
|
+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 java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.UUID;
|
|
|
|
|
+import java.util.function.BiConsumer;
|
|
|
|
|
+import java.util.function.BiFunction;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
+
|
|
|
|
|
+public class ClanCommand implements CommandExecutor, TabCompleter {
|
|
|
|
|
+ private ClanManager manager;
|
|
|
|
|
+ private CommandNode rootCommand;
|
|
|
|
|
+
|
|
|
|
|
+ public ClanCommand(ClanManager manager) {
|
|
|
|
|
+ this.manager = manager;
|
|
|
|
|
+ this.rootCommand = new CommandNode("clan", "Main clan command", null);
|
|
|
|
|
+ setupDefaultCommands();
|
|
|
|
|
+ }
|
|
|
|
|
+ private void setupDefaultCommands() {
|
|
|
|
|
+ // Register default commands
|
|
|
|
|
+
|
|
|
|
|
+ registerCommand("list", "List all clans", this::handleList);
|
|
|
|
|
+ registerCommand("help", "Gives information about the use of clan commands", this::handleHelp);
|
|
|
|
|
+ registerCommand("leave", "Leave your current clan", this::handleLeaveClan);
|
|
|
|
|
+ registerCommand("reload", "Reload the clan Plugin", this::handleReload);
|
|
|
|
|
+ registerCommand("members", "Show the members of your clan", this::handleShowMembers);
|
|
|
|
|
+ registerCommand("save", "Save all clans and Claims", this::handleSave);
|
|
|
|
|
+ //registerCommand("menu", "Shows a GUI to handle your clan if you are the owner", this::handleGUI);
|
|
|
|
|
+ CommandNode claimNode = registerCommand("claim", "Claim land for your clan", this::handleClaim);
|
|
|
|
|
+ claimNode.registerSubCommand("info", "Get information about your claims", this::infoClaims);
|
|
|
|
|
+ claimNode.registerSubCommand("removeAll", "Remove all current claims", this::removeAllClaims);
|
|
|
|
|
+
|
|
|
|
|
+ CommandNode acceptNode = registerCommand("acceptRequest", "Accept a pending request of a player", this::handleAcceptRequest);
|
|
|
|
|
+ acceptNode.setTabCompleter(this::completeRequests);
|
|
|
|
|
+
|
|
|
|
|
+ CommandNode declineNode = registerCommand("declineRequest", "Decline a pending request of a player", this::handleDeclineRequest);
|
|
|
|
|
+ declineNode.setTabCompleter(this::completeRequests);
|
|
|
|
|
+
|
|
|
|
|
+ CommandNode removeNode = registerCommand("remove", "Remove a Clan", this::removeClan);
|
|
|
|
|
+ removeNode.setTabCompleter(this::completeClans);
|
|
|
|
|
+
|
|
|
|
|
+ CommandNode joinNode = registerCommand("join", "Join a clan", this::handleJoin);
|
|
|
|
|
+ joinNode.setTabCompleter(this::completeClans);
|
|
|
|
|
+
|
|
|
|
|
+ CommandNode ruleNode = registerCommand("rule", "Manage clan rules", null);
|
|
|
|
|
+ ruleNode.registerSubCommand("list", "List all rules", this::handleRuleList);
|
|
|
|
|
+ ruleNode.registerSubCommand("set", "Set a rule value", this::handleRuleSet)
|
|
|
|
|
+ .setTabCompleter(this::completeRules);
|
|
|
|
|
+ ruleNode.registerSubCommand("add", "Add a new rule", this::handleRuleAdd);
|
|
|
|
|
+ ruleNode.registerSubCommand("remove", "Remove a rule", this::handleRuleRemove)
|
|
|
|
|
+ .setTabCompleter(this::completeRules);
|
|
|
|
|
+
|
|
|
|
|
+ registerCommand("create", "Create a new clan", this::handleCreate);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleSave(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if(!sender.isOp()) return;
|
|
|
|
|
+ Main.getInstance().getClanModule().getClanManager().saveClans();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void removeAllClaims(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if(!(sender instanceof Player player)) return;
|
|
|
|
|
+ Main.getInstance().getClanModule().getClaimManager().removeAllClaims();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void infoClaims(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if(!(sender instanceof Player player)) return;
|
|
|
|
|
+ UUID uuid = player.getUniqueId();
|
|
|
|
|
+ if(manager.getMyClan(uuid) == null) return;
|
|
|
|
|
+ for(Claim claim : manager.getMyClan(uuid).getClaims()){
|
|
|
|
|
+ ClanModule.sendText(player, "info about your claim");
|
|
|
|
|
+ ClanModule.sendText(player, claim.getVolume()+" is this volume");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleClaim(CommandSender sender, String[] strings) {
|
|
|
|
|
+ sender.sendMessage("Nothing yet implemented! come back later!");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleGUI(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if(!(sender instanceof Player player)) return;
|
|
|
|
|
+ if(manager.getMyClan(player.getUniqueId()) == null) return;
|
|
|
|
|
+ new ClanGUI(manager, player).open();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ private void handleDeclineRequest(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if (!(sender instanceof Player player) || strings[0] == null || strings[0].isEmpty()) return;
|
|
|
|
|
+ UUID uuid = player.getUniqueId();
|
|
|
|
|
+ Clan clan = manager.getMyClan(uuid);
|
|
|
|
|
+ clan.denyRequest(uuid, strings[0]);
|
|
|
|
|
+ ClanModule.sendText(player, "You declined the request from " + strings[0] + ".");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleAcceptRequest(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if (!(sender instanceof Player player) || strings[0] == null || strings[0].isEmpty()) return;
|
|
|
|
|
+ UUID uuid = player.getUniqueId();
|
|
|
|
|
+ Clan clan = manager.getMyClan(uuid);
|
|
|
|
|
+ clan.acceptRequest(uuid, strings[0]);
|
|
|
|
|
+ ClanModule.sendText(player, "You accepted the request from " + strings[0] + ".");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleShowMembers(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if (!(sender instanceof Player player)) return;
|
|
|
|
|
+ UUID uuid = player.getUniqueId();
|
|
|
|
|
+ Clan clan = manager.getMyClan(uuid);
|
|
|
|
|
+ if(clan == null) return;
|
|
|
|
|
+ ClanModule.sendText(player, "§6=== Clan Members - " + clan.getName() + " ===");
|
|
|
|
|
+ Player owner = clan.getOwner();
|
|
|
|
|
+ ClanModule.sendText(player,
|
|
|
|
|
+ Component.text("Owner: ", NamedTextColor.RED)
|
|
|
|
|
+ .append(Component.text(owner.getName(), NamedTextColor.GRAY)));
|
|
|
|
|
+ for(UUID member : clan.getMembers()){
|
|
|
|
|
+ ClanModule.sendText(player, Bukkit.getPlayer(member).getName());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleReload(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if(sender.isOp()) {
|
|
|
|
|
+ reload();
|
|
|
|
|
+ ClanModule.sendText(sender, "Reloading...");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleLeaveClan(CommandSender sender, String[] strings) {
|
|
|
|
|
+ if (!(sender instanceof Player player)) return;
|
|
|
|
|
+ UUID uuid = player.getUniqueId();
|
|
|
|
|
+ Clan clan = manager.getMyClan(uuid);
|
|
|
|
|
+ if(manager.leaveClan(uuid)){
|
|
|
|
|
+ ClanModule.sendText(player,"You left your Clan ");
|
|
|
|
|
+ if(clan.getOwner().equals(player)){
|
|
|
|
|
+ manager.removeClan(clan.getName());
|
|
|
|
|
+ ClanModule.sendText(player,"The clan was deleted since you are the only one left!");
|
|
|
|
|
+ }
|
|
|
|
|
+ }else{
|
|
|
|
|
+ ClanModule.sendText(player,"You cannot leave this clan! Either join a clan or if you are an owner, please remove all members first!");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleHelp(CommandSender sender, String[] strings) {
|
|
|
|
|
+ sendHelp(sender);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void removeClan(CommandSender commandSender, String[] strings) {
|
|
|
|
|
+ if(!commandSender.isOp()) return;
|
|
|
|
|
+ if(strings[0] != null && !strings[0].isEmpty()) manager.removeClan(strings[0]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleCreate(CommandSender commandSender, String[] strings) {
|
|
|
|
|
+ if (!(commandSender instanceof Player player)) return;
|
|
|
|
|
+
|
|
|
|
|
+ String name = String.join("-", strings);
|
|
|
|
|
+ if (manager.getMyClan(player.getUniqueId()) != null){
|
|
|
|
|
+ ClanModule.sendText(player,"You are already in a clan! Leave your clan first!");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(manager.createClan(player, name)) ClanModule.sendText(player,"Creating the Clan " + name + " ...");
|
|
|
|
|
+ else ClanModule.sendText(player,"The Name for the Clan " + name + " is already taken or you are already in a clan!");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleRuleRemove(CommandSender commandSender, String[] strings) {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleRuleAdd(CommandSender commandSender, String[] strings) {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleRuleSet(CommandSender commandSender, String[] strings) {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleRuleList(CommandSender commandSender, String[] strings) {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Helper method to easily register commands
|
|
|
|
|
+ public CommandNode registerCommand(String name, String description, BiConsumer<CommandSender, String[]> 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<String> 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 /clan 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<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
|
|
|
|
+ List<String> suggestions = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ if (args.length == 0) {
|
|
|
|
|
+ return suggestions;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Start at root and traverse
|
|
|
|
|
+ CommandNode currentNode = rootCommand;
|
|
|
|
|
+ List<String> 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=== Clan Commands ===");
|
|
|
|
|
+ for (CommandNode cmd : rootCommand.getSubCommands()) {
|
|
|
|
|
+ sender.sendMessage("§e/clan " + 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());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Dynamic registration API
|
|
|
|
|
+ public void registerDynamicCommand(String path, String description,
|
|
|
|
|
+ BiConsumer<CommandSender, String[]> executor,
|
|
|
|
|
+ BiFunction<CommandSender, String[], List<String>> tabCompleter) {
|
|
|
|
|
+ String[] parts = path.split("\\.");
|
|
|
|
|
+ CommandNode currentNode = rootCommand;
|
|
|
|
|
+
|
|
|
|
|
+ for (String part : parts) {
|
|
|
|
|
+ CommandNode nextNode = currentNode.getSubCommand(part);
|
|
|
|
|
+ if (nextNode == null) {
|
|
|
|
|
+ nextNode = new CommandNode(part, "", null);
|
|
|
|
|
+ currentNode.addSubCommand(nextNode);
|
|
|
|
|
+ }
|
|
|
|
|
+ currentNode = nextNode;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ currentNode.setExecutor(executor);
|
|
|
|
|
+ currentNode.setTabCompleter(tabCompleter);
|
|
|
|
|
+ if (!description.isEmpty()) {
|
|
|
|
|
+ // Can't directly set description as it's final, would need to modify CommandNode
|
|
|
|
|
+ // or use a different approach
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Example command handlers
|
|
|
|
|
+ private void handleList(CommandSender sender, String[] args) {
|
|
|
|
|
+ ClanModule.sendText(sender,"Aktuelle Liste an Clans: ");
|
|
|
|
|
+ for (Clan clan : manager.getClans()) {
|
|
|
|
|
+ ClanModule.sendText(sender,clan.getName());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void handleJoin(CommandSender sender, String[] args) {
|
|
|
|
|
+ if (!(sender instanceof Player player)) return;
|
|
|
|
|
+ if (args.length < 1) {
|
|
|
|
|
+ ClanModule.sendText(sender,"Usage: /clan join <clan>");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(manager.joinClan(player.getUniqueId(), args[0])) ClanModule.sendText(player, "Sent a request to join the clan " + args[0]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<String> completeClans(CommandSender sender, String[] args) {
|
|
|
|
|
+ if(!(sender instanceof Player player)) return List.of("Your not a player!");
|
|
|
|
|
+ String partial = args.length > 0 ? args[args.length - 1].toLowerCase() : "";
|
|
|
|
|
+ if(manager.getClans() == null) return List.of("No Clan found!");
|
|
|
|
|
+
|
|
|
|
|
+ return manager.getClans().stream()
|
|
|
|
|
+ .map(Clan::getName)
|
|
|
|
|
+ .filter(name -> name.toLowerCase().startsWith(partial))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<String> completeRules(CommandSender sender, String[] args) {
|
|
|
|
|
+ if(!(sender instanceof Player player)) return List.of("Your not a player!");
|
|
|
|
|
+
|
|
|
|
|
+ Clan clan = manager.getMyClan(player.getUniqueId());
|
|
|
|
|
+ if (clan == null) return List.of("You are not in a clan!");
|
|
|
|
|
+ if (clan.getRules() == null) return List.of("No rules set yet!");
|
|
|
|
|
+
|
|
|
|
|
+ String partial = args.length > 0 ? args[args.length - 1].toLowerCase() : "";
|
|
|
|
|
+ return clan.getRules().stream()
|
|
|
|
|
+ .map(Rule::getName)
|
|
|
|
|
+ .filter(name -> name.toLowerCase().startsWith(partial))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+ private List<String> completeRequests(CommandSender sender, String[] args) {
|
|
|
|
|
+ if(!(sender instanceof Player player)) return List.of("Your not a player!");
|
|
|
|
|
+
|
|
|
|
|
+ Clan clan = manager.getMyClan(player.getUniqueId());
|
|
|
|
|
+ if (clan == null) return List.of("You are not in a clan!");
|
|
|
|
|
+ String partial = args.length > 0 ? args[args.length - 1].toLowerCase() : "";
|
|
|
|
|
+ return clan.getRequests().stream()
|
|
|
|
|
+ .filter(name -> name.toLowerCase().startsWith(partial))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void reload() {
|
|
|
|
|
+ setupDefaultCommands();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|