diff --git a/pom.xml b/pom.xml index 9c550e3..fe745f6 100644 --- a/pom.xml +++ b/pom.xml @@ -51,11 +51,6 @@ org.javassist:javassist - - - - - diff --git a/src/main/java/buttondevteam/chat/ChatProcessing.java b/src/main/java/buttondevteam/chat/ChatProcessing.java index 26f46a7..419f89d 100644 --- a/src/main/java/buttondevteam/chat/ChatProcessing.java +++ b/src/main/java/buttondevteam/chat/ChatProcessing.java @@ -1,5 +1,32 @@ package buttondevteam.chat; +import buttondevteam.chat.commands.UnlolCommand; +import buttondevteam.chat.commands.ucmds.admin.DebugCommand; +import buttondevteam.chat.formatting.ChatFormatter; +import buttondevteam.chat.formatting.TellrawEvent; +import buttondevteam.chat.formatting.TellrawPart; +import buttondevteam.chat.formatting.TellrawSerializer; +import buttondevteam.chat.listener.PlayerListener; +import buttondevteam.lib.TBMCChatEvent; +import buttondevteam.lib.TBMCChatEventBase; +import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.chat.*; +import buttondevteam.lib.player.ChromaGamerBase; +import buttondevteam.lib.player.TBMCPlayer; +import buttondevteam.lib.player.TBMCPlayerBase; +import com.earth2me.essentials.Essentials; +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; +import lombok.val; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Sound; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Objective; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -8,378 +35,312 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.regex.Pattern; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Sound; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.scoreboard.Objective; - -import com.earth2me.essentials.Essentials; -import com.google.common.collect.Lists; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; - -import buttondevteam.chat.commands.UnlolCommand; -import buttondevteam.chat.commands.ucmds.admin.DebugCommand; -import buttondevteam.chat.formatting.*; -import buttondevteam.lib.TBMCChatEvent; -import buttondevteam.lib.TBMCChatEventBase; -import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.chat.Channel; -import buttondevteam.lib.chat.TellrawSerializableEnum; -import buttondevteam.lib.player.TBMCPlayer; -import buttondevteam.lib.player.TBMCPlayerBase; -import lombok.val; -import buttondevteam.chat.listener.PlayerListener; -import buttondevteam.lib.chat.*; - public class ChatProcessing { - private static final Pattern NULL_MENTION_PATTERN = Pattern.compile("null"); - private static final Pattern CYAN_PATTERN = Pattern.compile("cyan"); - private static final Pattern ESCAPE_PATTERN = Pattern.compile("\\\\"); - private static final Pattern CONSOLE_PING_PATTERN = Pattern.compile("(?i)" + Pattern.quote("@console")); - private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)"); - private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),]+)"); - private static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+"); - private static final Pattern UNDERLINED_PATTERN = Pattern.compile("\\_"); - private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*"); - private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*"); - private static final Pattern CODE_PATTERN = Pattern.compile("`"); - private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]])\\]\\(([^\\(\\)])\\)"); - private static final Color[] RainbowPresserColors = new Color[] { Color.Red, Color.Gold, Color.Yellow, Color.Green, - Color.Blue, Color.DarkPurple }; - private static boolean pingedconsole = false; + private static final Pattern NULL_MENTION_PATTERN = Pattern.compile("null"); + private static final Pattern CYAN_PATTERN = Pattern.compile("cyan"); + private static final Pattern ESCAPE_PATTERN = Pattern.compile("\\\\"); + private static final Pattern CONSOLE_PING_PATTERN = Pattern.compile("(?i)" + Pattern.quote("@console")); + private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)"); + private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),]+)"); + private static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+"); + private static final Pattern UNDERLINED_PATTERN = Pattern.compile("_"); + private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*"); + private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*"); + private static final Pattern CODE_PATTERN = Pattern.compile("`"); + private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]])\\]\\(([^()])\\)"); + private static final Pattern SOMEONE_PATTERN = Pattern.compile("@someone"); //TODO + private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green, + Color.Blue, Color.DarkPurple}; + private static boolean pingedconsole = false; - public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder().regex(ESCAPE_PATTERN).build(); + public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder().regex(ESCAPE_PATTERN).build(); - private static ArrayList commonFormatters = Lists.newArrayList( - ChatFormatter.builder().regex(BOLD_PATTERN).bold(true).removeCharCount((short) 2).range(true) - .priority(Priority.High).build(), - ChatFormatter.builder().regex(ITALIC_PATTERN).italic(true).removeCharCount((short) 1).range(true).build(), - ChatFormatter.builder().regex(UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).range(true) - .build(), - ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").build(), - ChatFormatter.builder().regex(NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature - ChatFormatter.builder().regex(CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder) -> { - if (!pingedconsole) { - System.out.print("\007"); - pingedconsole = true; // Will set it to false in ProcessChat - } - return match; - }).priority(Priority.High).build(), + private static ArrayList commonFormatters = Lists.newArrayList( + ChatFormatter.builder().regex(BOLD_PATTERN).bold(true).removeCharCount((short) 2).range(true) + .priority(Priority.High).build(), + ChatFormatter.builder().regex(ITALIC_PATTERN).italic(true).removeCharCount((short) 1).range(true).build(), + ChatFormatter.builder().regex(UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).range(true) + .build(), + ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").build(), + ChatFormatter.builder().regex(NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature + ChatFormatter.builder().regex(CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder) -> { + if (!pingedconsole) { + System.out.print("\007"); + pingedconsole = true; // Will set it to false in ProcessChat + } + return match; + }).priority(Priority.High).build(), - ChatFormatter.builder().regex(HASHTAG_PATTERN).color(Color.Blue).openlink("https://twitter.com/hashtag/$1") - .priority(Priority.High).build(), - ChatFormatter.builder().regex(CYAN_PATTERN).color(Color.Aqua).build(), // #55 - ChatFormatter.builder().regex(CODE_PATTERN).color(Color.DarkGray).removeCharCount((short) 1).range(true) - .build(), - ChatFormatter.builder().regex(MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder) -> { - return match; // TODO! - }).build()); - private static Gson gson = new GsonBuilder() - .registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum()) - .registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection()) - .registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool()) - .registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create(); + ChatFormatter.builder().regex(HASHTAG_PATTERN).color(Color.Blue).openlink("https://twitter.com/hashtag/$1") + .priority(Priority.High).build(), + ChatFormatter.builder().regex(CYAN_PATTERN).color(Color.Aqua).build(), // #55 + ChatFormatter.builder().regex(CODE_PATTERN).color(Color.DarkGray).removeCharCount((short) 1).range(true) + .build(), + ChatFormatter.builder().regex(MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder) -> { + return match; // TODO! + }).build()); + private static Gson gson = new GsonBuilder() + .registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum()) + .registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection()) + .registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool()) + .registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create(); - private ChatProcessing() { - } + private ChatProcessing() { + } - public static boolean ProcessChat(TBMCChatEvent e) { - Channel channel = e.getChannel(); - CommandSender sender = e.getSender(); - String message = e.getMessage(); - long processstart = System.nanoTime(); - if (PluginMain.essentials == null) - PluginMain.essentials = (Essentials) (Bukkit.getPluginManager().getPlugin("Essentials")); - Player player = (sender instanceof Player ? (Player) sender : null); + public static boolean ProcessChat(TBMCChatEvent e) { + Channel channel = e.getChannel(); + CommandSender sender = e.getSender(); + String message = e.getMessage(); + long processstart = System.nanoTime(); + if (PluginMain.essentials == null) + PluginMain.essentials = (Essentials) (Bukkit.getPluginManager().getPlugin("Essentials")); + Player player = (sender instanceof Player ? (Player) sender : null); - if (player != null && PluginMain.essentials.getUser(player).isMuted()) - return true; + if (player != null && PluginMain.essentials.getUser(player).isMuted()) + return true; - doFunStuff(sender, e, message); + doFunStuff(sender, e, message); - ChatPlayer mp = null; - if (player != null) - mp = TBMCPlayerBase.getPlayer(player.getUniqueId(), ChatPlayer.class); + ChatPlayer mp = null; + if (player != null) + mp = TBMCPlayerBase.getPlayer(player.getUniqueId(), ChatPlayer.class); - Color colormode = channel.color; - if (mp != null && mp.OtherColorMode != null) - colormode = mp.OtherColorMode; - if (message.startsWith(">")) - colormode = Color.Green; - // If greentext, ignore channel or player colors + Color colormode = channel.color; + if (mp != null && mp.OtherColorMode != null) + colormode = mp.OtherColorMode; + if (message.startsWith(">")) + colormode = Color.Green; + // If greentext, ignore channel or player colors - ArrayList formatters = addFormatters(colormode); - if (colormode == channel.color && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color - final AtomicInteger rpc = new AtomicInteger(0); - formatters.add(ChatFormatter.builder().color(colormode).onmatch((match, cf) -> { - cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]); - return match; - }).build()); - } - pingedconsole = false; // Will set it to true onmatch (static constructor) - final String channelidentifier = getChannelID(channel, sender); + ArrayList formatters = addFormatters(colormode); + if (colormode == channel.color && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color + final AtomicInteger rpc = new AtomicInteger(0); + formatters.add(ChatFormatter.builder().color(colormode).onmatch((match, cf) -> { + cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]); + return match; + }).build()); + } + pingedconsole = false; // Will set it to true onmatch (static constructor) + final String channelidentifier = getChannelID(channel, sender); - TellrawPart json = createTellraw(sender, message, player, mp, channelidentifier); - long combinetime = System.nanoTime(); - ChatFormatter.Combine(formatters, message, json); - combinetime = System.nanoTime() - combinetime; - String jsonstr = toJson(json); - if (jsonstr.length() >= 32767) { - sender.sendMessage( - "§cError: Message too long. Try shortening it, or remove hashtags and other formatting."); - return true; - } - DebugCommand.SendDebugMessage(jsonstr); + TellrawPart json = createTellraw(sender, message, player, mp, channelidentifier); + long combinetime = System.nanoTime(); + ChatFormatter.Combine(formatters, message, json); + combinetime = System.nanoTime() - combinetime; + String jsonstr = toJson(json); + if (jsonstr.length() >= 32767) { + sender.sendMessage( + "§cError: Message too long. Try shortening it, or remove hashtags and other formatting."); + return true; + } + DebugCommand.SendDebugMessage(jsonstr); - try { - if (channel.filteranderrormsg != null) { - Objective obj = PluginMain.SB.getObjective(channel.ID); - int score = -1; - for (Player p : Bukkit.getOnlinePlayers()) { - final int mcScore; - if (player != null - && PluginMain.essentials.getUser(p).isIgnoredPlayer(PluginMain.essentials.getUser(player))) - mcScore = -1; // Don't send the message to them - else - mcScore = VanillaUtils.getMCScoreIfChatOn(p, e); - obj.getScore(p.getName()) - .setScore(p.getUniqueId().equals(player == null ? null : player.getUniqueId()) // p.UniqueID==player?.UniqueID - ? score = mcScore : mcScore); - } - if (score == -1) // Even if the player object isn't null, it may not be in OnlinePlayers - score = e.getMCScore(sender); - if (score < 0) // Never send messages to score below 0 - sender.sendMessage("§cYou don't have permission to send this message or something went wrong"); - else { - PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console, - String.format("tellraw @a[score_%s=%d,score_%s_min=%d] %s", channel.ID, score, channel.ID, - score, jsonstr)); - if (e.getChannel().ID.equals(PluginMain.TownChat.ID) - || e.getChannel().ID.equals(PluginMain.NationChat.ID)) { - ((List) json.getExtra()).add(0, new TellrawPart("[SPY]")); - jsonstr = toJson(json); - Bukkit.getServer().dispatchCommand(PluginMain.Console, String.format( - "tellraw @a[score_%s=1000,score_%s_min=1000] %s", channel.ID, channel.ID, jsonstr)); - } - } - } else - PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console, - String.format("tellraw @a %s", jsonstr)); - } catch (Exception ex) { - TBMCCoreAPI.SendException("An error occured while sending a chat message!", ex); - sender.sendMessage("§cAn error occured while sending the message."); - return true; - } - PluginMain.Instance.getServer().getConsoleSender() - .sendMessage(String.format("%s <%s§r> %s", channelidentifier, getSenderName(sender, player), message)); - DebugCommand.SendDebugMessage( - "-- Full ChatProcessing time: " + (System.nanoTime() - processstart) / 1000000f + " ms"); - DebugCommand.SendDebugMessage("-- ChatFormatter.Combine time: " + combinetime / 1000000f + " ms"); - return false; - } + try { + if (channel.filteranderrormsg != null) { + Objective obj = PluginMain.SB.getObjective(channel.ID); + int score = -1; + for (Player p : Bukkit.getOnlinePlayers()) { + final int mcScore; + if (player != null + && PluginMain.essentials.getUser(p).isIgnoredPlayer(PluginMain.essentials.getUser(player))) + mcScore = -1; // Don't send the message to them + else + mcScore = VanillaUtils.getMCScoreIfChatOn(p, e); + obj.getScore(p.getName()) + .setScore(p.getUniqueId().equals(player == null ? null : player.getUniqueId()) // p.UniqueID==player?.UniqueID + ? score = mcScore : mcScore); + } + if (score == -1) // Even if the player object isn't null, it may not be in OnlinePlayers + score = e.getMCScore(sender); + if (score < 0) // Never send messages to score below 0 + sender.sendMessage("§cYou don't have permission to send this message or something went wrong"); + else { + PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console, + String.format("tellraw @a[score_%s=%d,score_%s_min=%d] %s", channel.ID, score, channel.ID, + score, jsonstr)); + if (e.getChannel().ID.equals(PluginMain.TownChat.ID) + || e.getChannel().ID.equals(PluginMain.NationChat.ID)) { + ((List) json.getExtra()).add(0, new TellrawPart("[SPY]")); + jsonstr = toJson(json); + Bukkit.getServer().dispatchCommand(PluginMain.Console, String.format( + "tellraw @a[score_%s=1000,score_%s_min=1000] %s", channel.ID, channel.ID, jsonstr)); + } + } + } else + PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console, + String.format("tellraw @a %s", jsonstr)); + } catch (Exception ex) { + TBMCCoreAPI.SendException("An error occured while sending a chat message!", ex); + sender.sendMessage("§cAn error occured while sending the message."); + return true; + } + PluginMain.Instance.getServer().getConsoleSender() + .sendMessage(String.format("%s <%s§r> %s", channelidentifier, getSenderName(sender, player), message)); + DebugCommand.SendDebugMessage( + "-- Full ChatProcessing time: " + (System.nanoTime() - processstart) / 1000000f + " ms"); + DebugCommand.SendDebugMessage("-- ChatFormatter.Combine time: " + combinetime / 1000000f + " ms"); + return false; + } - static String toJson(TellrawPart json) { - String jsonstr = gson.toJson(json); - return jsonstr; - } + static String toJson(TellrawPart json) { + return gson.toJson(json); + } - static TellrawPart createTellraw(CommandSender sender, String message, Player player, ChatPlayer mp, - final String channelidentifier) { - TellrawPart json = new TellrawPart(""); - if (mp != null && mp.ChatOnly) { - json.addExtra(new TellrawPart("[C]") - .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Chat only"))); - } - json.addExtra( - new TellrawPart(channelidentifier) - .setHoverEvent( - TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, - new TellrawPart((sender instanceof IDiscordSender ? "From Discord\n" : "") - + "Copy message").setColor(Color.Blue))) - .setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND, message))); - json.addExtra(new TellrawPart(" <")); - json.addExtra( - new TellrawPart( - getSenderName( - sender, player)) - .setHoverEvent( - TellrawEvent - .create(TellrawEvent.HoverAction.SHOW_TEXT, - new TellrawPart("") - .addExtra(new TellrawPart(String.format( - "Flair: %s", - (mp != null ? mp.GetFormattedFlair() - : "-")))) - .addExtra(new TellrawPart(String.format( - "\nPlayername: %s\n", - (player != null ? player.getName() - : sender.getName()))) - .setColor(Color.Aqua)) - .addExtra(new TellrawPart(String.format( - "World: %s\n", - (player != null - ? player.getWorld().getName() - : "-")))) - .addExtra(new TellrawPart(String.format( - "Respect: %s%s%s", - (mp != null ? (mp.FCount().get() - / (double) mp.FDeaths().get()) - : "Infinite"), - (mp != null - && mp.UserName().get() != null - && !mp.UserName().get() - .isEmpty() - ? "\nUserName: " - + mp.UserName() - .get() - : ""), - (mp != null && mp.PlayerName().get() - .equals("\nAlpha_Bacca44") - ? "\nDeaths: " - + PlayerListener.AlphaDeaths - : "")))) - .addExtra(new TellrawPart( - "\nFor more, do /u info " - + sender.getName()))))); - json.addExtra(new TellrawPart("> ")); - return json; - } + static TellrawPart createTellraw(CommandSender sender, String message, Player player, ChatPlayer mp, + final String channelidentifier) { + TellrawPart json = new TellrawPart(""); + if (mp != null && mp.ChatOnly) { + json.addExtra(new TellrawPart("[C]") + .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Chat only"))); + } + json.addExtra( + new TellrawPart(channelidentifier) + .setHoverEvent( + TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, + new TellrawPart((sender instanceof IDiscordSender ? "From Discord\n" : "") + + "Copy message").setColor(Color.Blue))) + .setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND, message))); + json.addExtra(new TellrawPart(" <")); + TellrawPart hovertp = new TellrawPart(""); + if (mp != null) + hovertp.addExtra(new TellrawPart(mp.getInfo(ChromaGamerBase.InfoTarget.MCHover))); + json.addExtra(new TellrawPart(getSenderName(sender, player)) + .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, hovertp))); + json.addExtra(new TellrawPart("> ")); + return json; + } - private static String getSenderName(CommandSender sender, Player player) { - if (player == null) - return sender.getName(); - val res = PluginMain.TU.getResidentMap().get(player.getName().toLowerCase()); - if (res == null || !res.hasTown()) - return player.getDisplayName(); - try { - val clrs = PluginMain.TownColors.get(res.getTown().getName().toLowerCase()); - if (clrs == null) - return player.getDisplayName(); - StringBuilder ret = new StringBuilder(); - String name = ChatColor.stripColor(player.getDisplayName()); - AtomicInteger prevlen = new AtomicInteger(); - BiFunction coloredNamePart = (len, i) -> "§" - + Integer.toHexString(clrs[i].ordinal()) // 'Odds' are the last character is chopped off so we make sure to include all chars at the end - + (i + 1 == clrs.length ? name.substring(prevlen.get()) - : name.substring(prevlen.get(), prevlen.addAndGet(len))); - int len = name.length() / clrs.length; - val nclar = ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class).NameColorLocations().get(); - int[] ncl = nclar == null ? null : nclar.stream().mapToInt(Integer::intValue).toArray(); - if (ncl != null && (Arrays.stream(ncl).sum() != name.length() || ncl.length != clrs.length)) - ncl = null; // Reset if name length changed - if (name.charAt(0) == '~') { // Ignore ~ in nicknames - prevlen.incrementAndGet(); - ret.append("~"); - } - for (int i = 0; i < clrs.length; i++) - ret.append(coloredNamePart.apply(ncl == null ? len : ncl[i], i)); - return ret.toString(); - } catch (NotRegisteredException e) { - return player.getDisplayName(); - } - } + private static String getSenderName(CommandSender sender, Player player) { + if (player == null) + return sender.getName(); + val res = PluginMain.TU.getResidentMap().get(player.getName().toLowerCase()); + if (res == null || !res.hasTown()) + return player.getDisplayName(); + try { + val clrs = PluginMain.TownColors.get(res.getTown().getName().toLowerCase()); + if (clrs == null) + return player.getDisplayName(); + StringBuilder ret = new StringBuilder(); + String name = ChatColor.stripColor(player.getDisplayName()); + AtomicInteger prevlen = new AtomicInteger(); + BiFunction coloredNamePart = (len, i) -> "§" + + Integer.toHexString(clrs[i].ordinal()) // 'Odds' are the last character is chopped off so we make sure to include all chars at the end + + (i + 1 == clrs.length ? name.substring(prevlen.get()) + : name.substring(prevlen.get(), prevlen.addAndGet(len))); + int len = name.length() / clrs.length; + val nclar = ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class).NameColorLocations().get(); + int[] ncl = nclar == null ? null : nclar.stream().mapToInt(Integer::intValue).toArray(); + if (ncl != null && (Arrays.stream(ncl).sum() != name.length() || ncl.length != clrs.length)) + ncl = null; // Reset if name length changed + if (name.charAt(0) == '~') { // Ignore ~ in nicknames + prevlen.incrementAndGet(); + ret.append("~"); + } + for (int i = 0; i < clrs.length; i++) + ret.append(coloredNamePart.apply(ncl == null ? len : ncl[i], i)); + return ret.toString(); + } catch (NotRegisteredException e) { + return player.getDisplayName(); + } + } - static String getChannelID(Channel channel, CommandSender sender) { - final String channelidentifier = ("[" + (sender instanceof IDiscordSender ? "d|" : "") + channel.DisplayName) - + "]"; - return channelidentifier; - } + static String getChannelID(Channel channel, CommandSender sender) { + return ("[" + (sender instanceof IDiscordSender ? "§bD§r|" : "") + channel.DisplayName) + + "]"; + } - static ArrayList addFormatters(Color colormode) { - @SuppressWarnings("unchecked") - ArrayList formatters = (ArrayList) commonFormatters.clone(); + static ArrayList addFormatters(Color colormode) { + @SuppressWarnings("unchecked") + ArrayList formatters = (ArrayList) commonFormatters.clone(); - formatters.add( - ChatFormatter.builder().regex(ENTIRE_MESSAGE_PATTERN).color(colormode).priority(Priority.Low).build()); + formatters.add( + ChatFormatter.builder().regex(ENTIRE_MESSAGE_PATTERN).color(colormode).priority(Priority.Low).build()); - if (Bukkit.getOnlinePlayers().size() > 0) { - StringBuilder namesb = new StringBuilder("(?i)("); - for (Player p : Bukkit.getOnlinePlayers()) - namesb.append(p.getName()).append("|"); - namesb.deleteCharAt(namesb.length() - 1); - namesb.append(")"); - StringBuilder nicksb = new StringBuilder("(?i)("); - boolean addNickFormatter = false; - final int size = Bukkit.getOnlinePlayers().size(); - int index = 0; - for (Player p : Bukkit.getOnlinePlayers()) { - final String nick = PlayerListener.nicknames.inverse().get(p.getUniqueId()); - if (nick != null) { - nicksb.append(nick); - if (index < size - 1) { - nicksb.append("|"); - addNickFormatter = true; - } - } - index++; - } - nicksb.append(")"); + if (Bukkit.getOnlinePlayers().size() > 0) { + StringBuilder namesb = new StringBuilder("(?i)("); + for (Player p : Bukkit.getOnlinePlayers()) + namesb.append(p.getName()).append("|"); + namesb.deleteCharAt(namesb.length() - 1); + namesb.append(")"); + StringBuilder nicksb = new StringBuilder("(?i)("); + boolean addNickFormatter = false; + final int size = Bukkit.getOnlinePlayers().size(); + int index = 0; + for (Player p : Bukkit.getOnlinePlayers()) { + final String nick = PlayerListener.nicknames.inverse().get(p.getUniqueId()); + if (nick != null) { + nicksb.append(nick); + if (index < size - 1) { + nicksb.append("|"); + addNickFormatter = true; + } + } + index++; + } + nicksb.append(")"); - formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua) - .onmatch((match, builder) -> { - Player p = Bukkit.getPlayer(match); - if (p == null) { - PluginMain.Instance.getLogger() - .warning("Error: Can't find player " + match + " but was reported as online."); - return "§c" + match + "§r"; - } - ChatPlayer mpp = TBMCPlayer.getPlayer(p.getUniqueId(), ChatPlayer.class); - if (PlayerListener.NotificationSound == null) - p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn - else - p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f, - (float) PlayerListener.NotificationPitch); - String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor())); - return color + p.getName() + "§r"; - }).priority(Priority.High).build()); + formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua) + .onmatch((match, builder) -> { + Player p = Bukkit.getPlayer(match); + if (p == null) { + PluginMain.Instance.getLogger() + .warning("Error: Can't find player " + match + " but was reported as online."); + return "§c" + match + "§r"; + } + ChatPlayer mpp = TBMCPlayer.getPlayer(p.getUniqueId(), ChatPlayer.class); + if (PlayerListener.NotificationSound == null) + p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn + else + p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f, + (float) PlayerListener.NotificationPitch); + String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor())); + return color + p.getName() + "§r"; + }).priority(Priority.High).build()); - if (addNickFormatter) - formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua) - .onmatch((match, builder) -> { - if (PlayerListener.nicknames.containsKey(match)) { - Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match)); - if (p == null) { - PluginMain.Instance.getLogger().warning("Error: Can't find player nicknamed " - + match + " but was reported as online."); - return "§c" + match + "§r"; - } - if (PlayerListener.NotificationSound == null) - p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); - else - p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f, - (float) PlayerListener.NotificationPitch); - return PluginMain.essentials.getUser(p).getNickname(); - } - Bukkit.getServer().getLogger().warning("Player nicknamed " + match - + " not found in nickname map but was reported as online."); - return "§c" + match + "§r"; - }).priority(Priority.High).build()); - } - return formatters; - } + if (addNickFormatter) + formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua) + .onmatch((match, builder) -> { + if (PlayerListener.nicknames.containsKey(match)) { + Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match)); + if (p == null) { + PluginMain.Instance.getLogger().warning("Error: Can't find player nicknamed " + + match + " but was reported as online."); + return "§c" + match + "§r"; + } + if (PlayerListener.NotificationSound == null) + p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); + else + p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f, + (float) PlayerListener.NotificationPitch); + return PluginMain.essentials.getUser(p).getNickname(); + } + Bukkit.getServer().getLogger().warning("Player nicknamed " + match + + " not found in nickname map but was reported as online."); + return "§c" + match + "§r"; + }).priority(Priority.High).build()); + } + return formatters; + } - static void doFunStuff(CommandSender sender, TBMCChatEventBase event, String message) { - if (PlayerListener.ActiveF && !PlayerListener.Fs.contains(sender) && message.equalsIgnoreCase("F")) - PlayerListener.Fs.add(sender); + static void doFunStuff(CommandSender sender, TBMCChatEventBase event, String message) { + if (PlayerListener.ActiveF && !PlayerListener.Fs.contains(sender) && message.equalsIgnoreCase("F")) + PlayerListener.Fs.add(sender); - String msg = message.toLowerCase(); - val lld = new UnlolCommand.LastlolData(sender, event, System.nanoTime()); - boolean add = false; - if (add = msg.contains("lol")) - lld.setLolornot(true); - else { - for (int i = 0; i < PlayerListener.LaughStrings.length; i++) { - if (add = msg.contains(PlayerListener.LaughStrings[i])) { - lld.setLolornot(false); - break; - } - } - } - if (add) - UnlolCommand.Lastlol.put(event.getChannel(), lld); - } + String msg = message.toLowerCase(); + val lld = new UnlolCommand.LastlolData(sender, event, System.nanoTime()); + boolean add; + if (add = msg.contains("lol")) + lld.setLolornot(true); + else { + for (int i = 0; i < PlayerListener.LaughStrings.length; i++) { + if (add = msg.contains(PlayerListener.LaughStrings[i])) { + lld.setLolornot(false); + break; + } + } + } + if (add) + UnlolCommand.Lastlol.put(event.getChannel(), lld); + } } diff --git a/src/main/java/buttondevteam/chat/PluginMain.java b/src/main/java/buttondevteam/chat/PluginMain.java index 4947bef..7ea6e1f 100644 --- a/src/main/java/buttondevteam/chat/PluginMain.java +++ b/src/main/java/buttondevteam/chat/PluginMain.java @@ -1,9 +1,28 @@ package buttondevteam.chat; +import buttondevteam.chat.commands.YeehawCommand; +import buttondevteam.chat.commands.ucmds.TownColorCommand; +import buttondevteam.chat.listener.PlayerListener; +import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.chat.Channel; +import buttondevteam.lib.chat.Channel.RecipientTestResult; +import buttondevteam.lib.chat.Color; +import buttondevteam.lib.chat.TBMCChatAPI; +import buttondevteam.lib.player.TBMCPlayerBase; +import com.earth2me.essentials.Essentials; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.palmergames.bukkit.towny.Towny; +import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; +import com.palmergames.bukkit.towny.object.Nation; +import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.object.Town; +import com.palmergames.bukkit.towny.object.TownyUniverse; +import lombok.val; import net.milkbowl.vault.chat.Chat; import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.permission.Permission; - import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; @@ -17,45 +36,15 @@ import org.dynmap.towny.DynmapTownyPlugin; import org.htmlcleaner.HtmlCleaner; import org.htmlcleaner.TagNode; -import buttondevteam.chat.commands.YeehawCommand; -import buttondevteam.chat.commands.ucmds.TownColorCommand; -import buttondevteam.chat.listener.PlayerListener; -import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.chat.Channel; -import buttondevteam.lib.chat.Color; -import buttondevteam.lib.chat.TBMCChatAPI; -import buttondevteam.lib.chat.Channel.RecipientTestResult; -import buttondevteam.lib.player.TBMCPlayerBase; -import lombok.val; - -import com.earth2me.essentials.Essentials; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.palmergames.bukkit.towny.Towny; -import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; -import com.palmergames.bukkit.towny.object.Nation; -import com.palmergames.bukkit.towny.object.Resident; -import com.palmergames.bukkit.towny.object.Town; -import com.palmergames.bukkit.towny.object.TownyUniverse; - -import java.io.*; -import java.lang.String; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -120,9 +109,8 @@ public class PluginMain extends JavaPlugin { // Translated to Java: 2015.07.15. setTownColor(dtp, entry.getKey(), entry.getValue()); }); - setupChat(); - setupEconomy(); - setupPermissions(); + if (!setupChat() || !setupEconomy() || !setupPermissions()) + getLogger().warning("Failed to set up chat or economy or permissions!"); new Thread(this::FlairGetterThreadMethod).start(); new Thread(new AnnouncerThread()).start(); @@ -296,17 +284,18 @@ public class PluginMain extends JavaPlugin { // Translated to Java: 2015.07.15. yc.load(file); PlayerListener.NotificationSound = yc.getString("notificationsound"); PlayerListener.NotificationPitch = yc.getDouble("notificationpitch"); - AnnounceTime = yc.getInt("announcetime"); + AnnounceTime = yc.getInt("announcetime", 15 * 60 * 1000); AnnounceMessages.addAll(yc.getStringList("announcements")); PlayerListener.AlphaDeaths = yc.getInt("alphadeaths"); val cs = yc.getConfigurationSection("towncolors"); if (cs != null) TownColors.putAll(cs.getValues(true).entrySet().stream() - .collect(Collectors.toMap(k -> k.getKey(), v -> ((List) v.getValue()).stream() - .map(c -> Color.valueOf(c)).toArray(Color[]::new)))); + .collect(Collectors.toMap(Map.Entry::getKey, v -> ((List) v.getValue()).stream() + .map(Color::valueOf).toArray(Color[]::new)))); TownColorCommand.ColorCount = (byte) yc.getInt("towncolorcount", 1); - } - PluginMain.Instance.getLogger().info("Loaded files!"); + PluginMain.Instance.getLogger().info("Loaded files!"); + } else + PluginMain.Instance.getLogger().info("No files to load, first run probably."); } catch (Exception e) { TBMCCoreAPI.SendException("Error while loading chat files!", e); } @@ -323,7 +312,7 @@ public class PluginMain extends JavaPlugin { // Translated to Java: 2015.07.15. yc.set("announcements", AnnounceMessages); yc.set("alphadeaths", PlayerListener.AlphaDeaths); yc.createSection("towncolors", TownColors.entrySet().stream().collect(Collectors.toMap(k -> k.getKey(), - v -> Arrays.stream(v.getValue()).map(c -> c.toString()).toArray(String[]::new)))); + v -> Arrays.stream(v.getValue()).map(Enum::toString).toArray(String[]::new)))); yc.set("towncolorcount", TownColorCommand.ColorCount); yc.save(file); PluginMain.Instance.getLogger().info("Saved files!"); diff --git a/src/main/java/buttondevteam/chat/commands/FTopCommand.java b/src/main/java/buttondevteam/chat/commands/FTopCommand.java new file mode 100644 index 0000000..0f27d3e --- /dev/null +++ b/src/main/java/buttondevteam/chat/commands/FTopCommand.java @@ -0,0 +1,43 @@ +package buttondevteam.chat.commands; + +import buttondevteam.chat.ChatPlayer; +import buttondevteam.lib.chat.CommandClass; +import buttondevteam.lib.chat.TBMCCommandBase; +import buttondevteam.lib.player.TBMCPlayerBase; +import org.bukkit.command.CommandSender; + +import java.io.File; +import java.util.Arrays; +import java.util.UUID; + +@CommandClass +public class FTopCommand extends TBMCCommandBase { + + @Override + public String[] GetHelpText(String arg0) { + return new String[]{ // + "§6---- F Top ----", // + "Shows the respect leaderboard" // + }; + } + + private final File playerdir = new File(TBMCPlayerBase.TBMC_PLAYERS_DIR); + private ChatPlayer[] cached; + private long lastcache = 0; + + @Override + public boolean OnCommand(CommandSender arg0, String arg1, String[] arg2) { + if (cached == null || lastcache < System.nanoTime() - 60000000000L) { // 1m - (no guarantees of nanoTime's relation to 0, so we need the null check too) + cached = Arrays.stream(playerdir.listFiles()) + .map(f -> TBMCPlayerBase.getPlayer( + UUID.fromString(f.getName().substring(0, f.getName().length() - 4)), ChatPlayer.class)) + .sorted((cp1, cp2) -> Float.compare((float) cp2.FCount().get() / (float) cp2.FDeaths().get(), + (float) cp1.FCount().get() / (float) cp1.FDeaths().get())) + .toArray(ChatPlayer[]::new); // TODO: Properly implement getting all players + lastcache = System.nanoTime(); + } + Arrays.stream(cached).limit(10); + return true; + } + +} diff --git a/src/main/java/buttondevteam/chat/listener/PlayerListener.java b/src/main/java/buttondevteam/chat/listener/PlayerListener.java index ce770b2..56c46af 100644 --- a/src/main/java/buttondevteam/chat/listener/PlayerListener.java +++ b/src/main/java/buttondevteam/chat/listener/PlayerListener.java @@ -1,37 +1,40 @@ package buttondevteam.chat.listener; -import java.util.*; -import java.util.Map.Entry; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.*; -import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.event.player.*; -import org.bukkit.event.server.ServerCommandEvent; -import org.bukkit.help.HelpTopic; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import buttondevteam.chat.*; +import buttondevteam.chat.ChatPlayer; +import buttondevteam.chat.ChatProcessing; +import buttondevteam.chat.PluginMain; import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.ChatChannelRegisterEvent; import buttondevteam.lib.chat.ChatRoom; import buttondevteam.lib.chat.TBMCChatAPI; +import buttondevteam.lib.player.ChromaGamerBase.InfoTarget; import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.TBMCPlayerGetInfoEvent; -import net.ess3.api.events.NickChangeEvent; -import buttondevteam.lib.player.ChromaGamerBase.InfoTarget; - import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.vexsoftware.votifier.model.Vote; import com.vexsoftware.votifier.model.VotifierEvent; +import net.ess3.api.events.NickChangeEvent; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.*; +import org.bukkit.event.server.ServerCommandEvent; +import org.bukkit.help.HelpTopic; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.*; +import java.util.Map.Entry; +import java.util.function.Consumer; +import java.util.function.Supplier; public class PlayerListener implements Listener { /** @@ -199,7 +202,7 @@ public class PlayerListener implements Listener { @EventHandler @SuppressWarnings("deprecation") - public void onVotifierEvent(VotifierEvent event) { + public void onVotifierEvent(VotifierEvent event) { //TODO: Move to teh Core eh Vote vote = event.getVote(); PluginMain.Instance.getLogger().info("Vote: " + vote); org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername());