package me.asofold.bpl.simplyvanish.command; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.server.ServerCommandEvent; /** * Stand-alone class for handling fake commands, to allow for ingame registration of new aliases and handling.<br> * "Lightweight commands" : checking PlayerCommandPreProcessEvent, if no command is available, check map and delegate.<br> * Uses trim/lowercase internally, a lot.<br> * Registers at highest priority currently. * @author mc_dev * */ public class LightCommands implements Listener { public static class LightCommand extends Command{ private CommandExecutor exe = null; public LightCommand(String name, String description, String usageMessage, List<String> aliases) { super(name, description, usageMessage, aliases); } @Override public boolean execute(CommandSender sender, String label, String[] args) { if (exe == null) return false; else return exe.onCommand(sender, this, label, args); } public void setExecutor(CommandExecutor commandExecutor){ this.exe = commandExecutor; } public CommandExecutor getExecutor(){ return exe; } } /** * If set all whitespace only parts will get removed before sending the command. */ public boolean aggressiveTrim = true; /** * Set command/message get set to this if handled by LightCommands. */ public String cmdNoOp = null; Map<String, LightCommand> commandMap = new HashMap<String, LightCommand>(); public boolean registerCommand(String label, Collection<String> aliases, CommandExecutor commandExecutor){ return registerCommand(label, null, null, aliases, commandExecutor); } public boolean registerCommand(String label, String description, String usage, Collection<String> aliases, CommandExecutor commandExecutor){ label = label.trim().toLowerCase(); List<String> aliasList = new LinkedList<String>(); for ( String alias : aliases){ aliasList.add(alias.trim().toLowerCase()); } if (commandMap.containsKey(label)) return false; LightCommand cmd = new LightCommand(label, description, usage, aliasList); cmd.setExecutor(commandExecutor); cmd.setUsage(usage); cmd.setDescription(description); this.commandMap.put(label, cmd); for (String alias : aliasList){ if (!commandMap.containsKey(alias)) commandMap.put(alias, cmd); } return true; } /** * Remove the binding for the alias or command, but not the other aliases / command. * @param label * @return */ public boolean removeAlias(String label){ LightCommand cmd = commandMap.remove(label.trim().toLowerCase()); if (cmd==null) return false; else return true; } /** * Remove command and aliases for the given label. * Does not work if label is an alias (!). * @param label * @return */ public boolean removeCommand(String label){ label = label.trim().toLowerCase(); LightCommand cmd = commandMap.get(label); if (cmd == null) return false; if (!label.equals(cmd.getLabel())) return false; commandMap.remove(label); for (String alias : cmd.getAliases()){ LightCommand candidate = commandMap.get(alias.trim().toLowerCase()); if (candidate == null) continue; if (!label.equals(candidate.getLabel())) continue; commandMap.remove(alias); } return true; } @EventHandler(priority = EventPriority.HIGHEST) public void onConsoleTryCommand(ServerCommandEvent event){ String msg = event.getCommand(); CommandSender sender = event.getSender(); if (processCommand(sender, msg)) event.setCommand(cmdNoOp); // TODO } @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerTryCommand(PlayerCommandPreprocessEvent event){ if ( event.isCancelled()) return; CommandSender sender = event.getPlayer(); String msg = event.getMessage(); if (msg == null) return; msg = msg.trim(); if (msg.startsWith("/")){ if (msg.length()>1) msg = msg.substring(1); else msg = ""; } if (processCommand(sender, msg)){ event.setCancelled(true); event.setMessage(cmdNoOp); } } /** * * @param sender * @param msg * @return */ public boolean processCommand(CommandSender sender, String msg){ if (msg == null) return false; if (sender == null) return false; String[] split = msg.split(" "); List<String> valid = new LinkedList<String>(); String label = null; LightCommand command = null; for (String part : split){ if (aggressiveTrim){ part = part.trim(); if (part.isEmpty()) continue; } if (label == null){ label = part; // ensure quick return. command = commandMap.get(label.trim().toLowerCase()); if (command == null) return false; } else valid.add(part); } if (label == null) return false; String[] args = new String[valid.size()]; if (args.length>0) valid.toArray(args); boolean res = command.execute(sender, label, args); if (res == false){ String usage = command.getUsage(); if (usage != null){ if (!usage.isEmpty()){ if (sender instanceof Player) sender.sendMessage(usage); else sender.sendMessage(ChatColor.stripColor(usage)); } } } return true; } public void clear() { commandMap.clear(); } }