package xyz.etztech.mixtape.listeners; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.ChatColor; 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; import xyz.etztech.mixtape.Alias; import xyz.etztech.mixtape.Database; import xyz.etztech.mixtape.Mixtape; import xyz.etztech.mixtape.MixtapeUtil; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class CommandPreprocessListener implements Listener { private final String ERROR = "Mixtape/Error"; private final Pattern PATTERN = Pattern.compile("<([^>]+)>"); private static Map loops = new HashMap<>(); Mixtape plugin; public CommandPreprocessListener(Mixtape plugin) { this.plugin = plugin; plugin.getServer().getPluginManager().registerEvents(this, plugin); } @EventHandler(priority= EventPriority.HIGH, ignoreCancelled=true) public void onServerCommandPreprocess(ServerCommandEvent event) { String command = event.getCommand(); if (command.startsWith("/")) { command = command.substring(1); } String base = command.split(" ")[0]; String[] args = command.trim().length() == base.trim().length() ? new String[0] : command.substring(base.length()+1).split(" "); event.setCancelled(handleEvent(Bukkit.getConsoleSender(), base, args)); } @EventHandler(priority= EventPriority.HIGH, ignoreCancelled=true) public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { String command = event.getMessage().substring(1); // Strip the slash String base = command.split(" ")[0]; String[] args = command.trim().length() == base.trim().length() ? new String[0] : command.substring(base.length()+1).split(" "); event.setCancelled(handleEvent(event.getPlayer(), base, args)); } private boolean handleEvent(CommandSender sender, String base, String[] args) { // Global aliases if (Mixtape.getGlobal()) { List configs = plugin.getConfig().getList("aliases", new ArrayList<>()); for (Object c : configs) { LinkedHashMap config = (LinkedHashMap) c; String configBase = MixtapeUtil.stripSlash(config.get("alias")); if (configBase.equalsIgnoreCase(base)) { String configCommand = MixtapeUtil.stripSlash(config.get("command")); String resolved = resolve(configCommand, args); if (!ERROR.equalsIgnoreCase(resolved)) { Bukkit.dispatchCommand(sender, resolved); } else { sender.sendMessage(ChatColor.RED + usage(base, configCommand)); } return true; } } } // Personal aliases if (sender instanceof Player) { Player player = (Player) sender; if (!increment(player.getUniqueId().toString())) { player.sendMessage(ChatColor.RED + "You went too deep! What is this, Inception?"); loops.put(player.getUniqueId().toString(), 0); return true; } // Command aliases List commands = Mixtape.getDatabase().getAliases(player.getUniqueId().toString(), Database.AliasType.COMMAND); for (Alias alias : commands) { if (alias.getFrom().equalsIgnoreCase(base)) { String resolved = resolve(alias.getTo(), args); if (!ERROR.equalsIgnoreCase(resolved)) { resolved = resolved.startsWith("/") ? resolved : "/" + resolved; player.chat(resolved); } else { player.sendMessage(ChatColor.RED + usage(base, alias.getTo())); } return true; } } // Chat aliases List chats = Mixtape.getDatabase().getAliases(player.getUniqueId().toString(), Database.AliasType.CHAT); for (Alias alias : chats) { if (alias.getFrom().equalsIgnoreCase(base)) { String resolved = resolve(alias.getTo(), args); if (!ERROR.equalsIgnoreCase(resolved)) { resolved = resolved.startsWith("/") ? "." + resolved : resolved; player.chat(resolved); } else { player.sendMessage(ChatColor.RED + usage(base, alias.getTo())); } loops.put(player.getUniqueId().toString(), 0); // Reset the inception counter for chat aliases before returning. return true; } } loops.put(player.getUniqueId().toString(), 0); } return false; } private String usage(String base, String template) { StringBuilder usage = new StringBuilder("/" + base); Matcher matcher = PATTERN.matcher(template); while (matcher.find()) { usage.append(" ").append(matcher.group(0)); } return usage.toString(); } private String resolve(String template, String... parts) { Matcher matcher = PATTERN.matcher(template); int idx = 0; try { while (matcher.find()) { template = template.replaceFirst(matcher.group(0), parts[idx]); idx++; } } catch (Exception ex) { return ERROR; } return template.trim() + " " + StringUtils.join(Arrays.copyOfRange(parts, idx, parts.length), " "); } private static boolean increment(String uuid) { Integer current = loops.get(uuid); current = current == null ? 1 : ++current; loops.put(uuid, current); return current <= Mixtape.getLoops(); } }