Mixtape/src/main/java/xyz/etztech/mixtape/listeners/CommandPreprocessListener.java

159 lines
6.1 KiB
Java

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<String, Integer> 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<String, String> config = (LinkedHashMap<String, String>) 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<Alias> 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<Alias> 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();
}
}