From 6da19877b8c310c0c8e76cd04ce7f8e7937c1e8f Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 22 Nov 2018 00:59:22 +0100 Subject: [PATCH 01/10] CI build branch fix: Origins From now on, the TRAVIS_BRANCH variable must be defined, either to master if the other projects (ButtonCore) are built locally, or the correct branch if not --- Notes.txt | 36 ---------------- pom.xml | 42 ++++++++++++++++++- .../buttondevteam/chat/ChatProcessing.java | 19 +++++---- .../commands/ucmds/admin/UpdatePlugin.java | 7 ++-- .../java/buttondevteam/chat/ChatFormatIT.java | 6 +-- 5 files changed, 59 insertions(+), 51 deletions(-) delete mode 100644 Notes.txt diff --git a/Notes.txt b/Notes.txt deleted file mode 100644 index 78af086..0000000 --- a/Notes.txt +++ /dev/null @@ -1,36 +0,0 @@ -Expected: - -***test*** -||- ||- - -||: bold --: italic - - -Actual: - -***test*** -||- ||- --|| -|| - - - - -nextSection: -*: italic(0) -**: -Either italic(0), bold(0) - Delete italic - bold(0), italic(1) - Delete italic - bold(0) -Or bold(0), italic(0) - Delete italic? - italic, italic - 0-length section as result, delete? - -takenStart, takenEnd -because it's ordered, the indexes will be either the same or ascending - - -^^ Implemented - -**test** -^ ^ <-- ! -start end -RemChar: 2 -tes* diff --git a/pom.xml b/pom.xml index f9ca404..67ca3b2 100644 --- a/pom.xml +++ b/pom.xml @@ -96,6 +96,46 @@ + @@ -143,7 +183,7 @@ com.github.TBMCPlugins.ButtonCore ButtonCore - master-SNAPSHOT + ${env.TRAVIS_BRANCH}-SNAPSHOT diff --git a/src/main/java/buttondevteam/chat/ChatProcessing.java b/src/main/java/buttondevteam/chat/ChatProcessing.java index 6591cd6..42ebf10 100644 --- a/src/main/java/buttondevteam/chat/ChatProcessing.java +++ b/src/main/java/buttondevteam/chat/ChatProcessing.java @@ -10,7 +10,10 @@ import buttondevteam.chat.listener.PlayerListener; import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatEventBase; import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.chat.*; +import buttondevteam.lib.chat.Channel; +import buttondevteam.lib.chat.Color; +import buttondevteam.lib.chat.Priority; +import buttondevteam.lib.chat.TellrawSerializableEnum; import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.TBMCPlayerBase; @@ -84,6 +87,7 @@ public class ChatProcessing { .registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool()) .registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create(); private static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"}; + static final String MCORIGIN = "Minecraft"; //Shouldn't change, like ever - TBMCPlayer.getFolderForType(TBMCPlayer.class) capitalized private ChatProcessing() { } @@ -126,9 +130,9 @@ public class ChatProcessing { }).build()); } pingedconsole = false; // Will set it to true onmatch (static constructor) - final String channelidentifier = getChannelID(channel, sender); + final String channelidentifier = getChannelID(channel, sender, e.getOrigin()); - TellrawPart json = createTellraw(sender, message, player, mp, e.getUser(), channelidentifier); + TellrawPart json = createTellraw(sender, message, player, mp, e.getUser(), channelidentifier, e.getOrigin()); long combinetime = System.nanoTime(); ChatFormatter.Combine(formatters, message, json); combinetime = System.nanoTime() - combinetime; @@ -192,7 +196,8 @@ public class ChatProcessing { } static TellrawPart createTellraw(CommandSender sender, String message, @Nullable Player player, - @Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier) { + @Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier, + String origin) { TellrawPart json = new TellrawPart(""); if (mp != null && mp.ChatOnly) { json.addExtra(new TellrawPart("[C]") @@ -202,7 +207,7 @@ public class ChatProcessing { new TellrawPart(channelidentifier) .setHoverEvent( TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, - new TellrawPart((sender instanceof IDiscordSender ? "From Discord\n" : "") + new TellrawPart((MCORIGIN.equals(origin) ? "" : "From " + origin + "n") + "Copy message").setColor(Color.Blue))) .setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND, message))); if (PluginMain.permission.has(sender, "tbmc.badge.diamond")) @@ -227,8 +232,8 @@ public class ChatProcessing { return player.getDisplayName(); } - static String getChannelID(Channel channel, CommandSender sender) { - return ("[" + (sender instanceof IDiscordSender ? "§8D§r|" : "") + channel.DisplayName) + static String getChannelID(Channel channel, CommandSender sender, String origin) { + return ("[" + (MCORIGIN.equals(origin) ? "" : "§8" + origin.substring(0, 1) + "§r|") + channel.DisplayName) + "]"; } diff --git a/src/main/java/buttondevteam/chat/commands/ucmds/admin/UpdatePlugin.java b/src/main/java/buttondevteam/chat/commands/ucmds/admin/UpdatePlugin.java index b60690e..be6f274 100644 --- a/src/main/java/buttondevteam/chat/commands/ucmds/admin/UpdatePlugin.java +++ b/src/main/java/buttondevteam/chat/commands/ucmds/admin/UpdatePlugin.java @@ -1,12 +1,11 @@ package buttondevteam.chat.commands.ucmds.admin; +import buttondevteam.chat.PluginMain; +import buttondevteam.component.updater.PluginUpdater; +import buttondevteam.lib.TBMCCoreAPI; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import buttondevteam.chat.PluginMain; -import buttondevteam.lib.PluginUpdater; -import buttondevteam.lib.TBMCCoreAPI; - public class UpdatePlugin extends AdminCommandBase { @Override diff --git a/src/test/java/buttondevteam/chat/ChatFormatIT.java b/src/test/java/buttondevteam/chat/ChatFormatIT.java index a1831cd..7929b4f 100644 --- a/src/test/java/buttondevteam/chat/ChatFormatIT.java +++ b/src/test/java/buttondevteam/chat/ChatFormatIT.java @@ -82,12 +82,12 @@ public class ChatFormatIT { @Test public void testMessage() { ArrayList cfs = ChatProcessing.addFormatters(Color.White); - final String chid = ChatProcessing.getChannelID(Channel.GlobalChat, sender); - final TellrawPart tp = ChatProcessing.createTellraw(sender, message, null, null, null, chid); + final String chid = ChatProcessing.getChannelID(Channel.GlobalChat, sender, ChatProcessing.MCORIGIN); + final TellrawPart tp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatProcessing.MCORIGIN); ChatFormatter.Combine(cfs, message, tp); System.out.println("Testing: " + message); // System.out.println(ChatProcessing.toJson(tp)); - final TellrawPart expectedtp = ChatProcessing.createTellraw(sender, message, null, null, null, chid); + final TellrawPart expectedtp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatProcessing.MCORIGIN); // System.out.println("Raw: " + ChatProcessing.toJson(expectedtp)); for (TellrawPart extra : extras) expectedtp.addExtra(extra); From dedfbacda6bd949ac6d5cc395bf73a2903e8dbb8 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 16 Dec 2018 19:16:05 +0100 Subject: [PATCH 02/10] NColor fix and only one TC/NC NColor fixed Only allowing one of a color combination Only allowing one of each nation color (except the default) --- .../chat/commands/ucmds/NColorCommand.java | 12 ++++---- .../ucmds/admin/NationColorCommand.java | 9 ++++++ .../ucmds/admin/TownColorCommand.java | 28 +++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/main/java/buttondevteam/chat/commands/ucmds/NColorCommand.java b/src/main/java/buttondevteam/chat/commands/ucmds/NColorCommand.java index 9ac3cff..88403b1 100644 --- a/src/main/java/buttondevteam/chat/commands/ucmds/NColorCommand.java +++ b/src/main/java/buttondevteam/chat/commands/ucmds/NColorCommand.java @@ -58,16 +58,16 @@ public class NColorCommand extends UCommandBase { player.sendMessage("§cYour town doesn't have a color set. The town mayor can set it using /u towncolor."); return true; } - if (nameparts.length < towncolors.length) { - player.sendMessage("§cYou need more vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1) + ")"); + if (nameparts.length < towncolors.length + 1) { //+1: Nation color + player.sendMessage("§cYou need more vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); //Nation color return true; } - if (nameparts.length > towncolors.length * 2) { - player.sendMessage("§cYou have waay too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1) + ")"); + if (nameparts.length > (towncolors.length + 1) * 2) { + player.sendMessage("§cYou have waay too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); return true; } - if (nameparts.length > towncolors.length) { - player.sendMessage("§cYou have too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1) + ")"); + if (nameparts.length > towncolors.length + 1) { + player.sendMessage("§cYou have too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); return true; } ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class).NameColorLocations() diff --git a/src/main/java/buttondevteam/chat/commands/ucmds/admin/NationColorCommand.java b/src/main/java/buttondevteam/chat/commands/ucmds/admin/NationColorCommand.java index 60564c5..ddc8e5b 100644 --- a/src/main/java/buttondevteam/chat/commands/ucmds/admin/NationColorCommand.java +++ b/src/main/java/buttondevteam/chat/commands/ucmds/admin/NationColorCommand.java @@ -2,6 +2,7 @@ package buttondevteam.chat.commands.ucmds.admin; import buttondevteam.chat.PluginMain; import buttondevteam.chat.listener.TownyListener; +import buttondevteam.lib.chat.Color; import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Town; import lombok.val; @@ -37,6 +38,14 @@ public class NationColorCommand extends AdminCommandBase { } val c = TownColorCommand.getColorOrSendError(args[1], sender); if (!c.isPresent()) return true; + if (!c.get().getName().equals(Color.White.getName())) { //Default nation color + for (val nc : PluginMain.NationColor.values()) { + if (nc.getName().equals(c.get().getName())) { + sender.sendMessage("§cAnother nation already uses this color!"); + return true; + } + } + } PluginMain.NationColor.put(args[0].toLowerCase(), c.get()); Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> { for (Town t : nation.getTowns()) diff --git a/src/main/java/buttondevteam/chat/commands/ucmds/admin/TownColorCommand.java b/src/main/java/buttondevteam/chat/commands/ucmds/admin/TownColorCommand.java index e1cd357..97224ad 100644 --- a/src/main/java/buttondevteam/chat/commands/ucmds/admin/TownColorCommand.java +++ b/src/main/java/buttondevteam/chat/commands/ucmds/admin/TownColorCommand.java @@ -10,6 +10,7 @@ import org.bukkit.command.CommandSender; import org.dynmap.towny.DynmapTownyPlugin; import java.util.Arrays; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -46,6 +47,33 @@ public class TownColorCommand extends AdminCommandBase { return true; clrs[i - 1] = c.get(); } + for (Map.Entry other : PluginMain.TownColors.entrySet()) { + Color nc, tnc; + try { + nc = PluginMain.NationColor.get(PluginMain.TU.getTownsMap().get(other.getKey()).getNation().getName().toLowerCase()); + } catch (Exception e) { //Too lazy for lots of null-checks and it may throw exceptions anyways + nc = null; + } + if (nc == null) nc = Color.White; //Default nation color + try { + tnc = PluginMain.NationColor.get(targetTown.getNation().getName().toLowerCase()); + } catch (Exception e) { + tnc = null; + } + if (tnc == null) tnc = Color.White; //Default nation color - TODO: Make configurable + if (nc.getName().equals(tnc.getName())) { + int C = 0; + if (clrs.length == other.getValue().length) + for (int i = 0; i < clrs.length; i++) + if (clrs[i].getName().equals(other.getValue()[i].getName())) + C++; + else break; + if (C == clrs.length) { + sender.sendMessage("§cThis town color combination is already used!"); + return true; + } + } + } PluginMain.TownColors.put(args[0].toLowerCase(), clrs); TownyListener.updateTownMembers(targetTown); From fd72e2de91e412eb427b2da29c63cd8019ea8f21 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 18 Dec 2018 00:52:56 +0100 Subject: [PATCH 03/10] No filteranderrormsg --- src/main/java/buttondevteam/chat/ChatProcessing.java | 2 +- src/main/java/buttondevteam/chat/listener/PlayerListener.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/buttondevteam/chat/ChatProcessing.java b/src/main/java/buttondevteam/chat/ChatProcessing.java index 42ebf10..02fe85c 100644 --- a/src/main/java/buttondevteam/chat/ChatProcessing.java +++ b/src/main/java/buttondevteam/chat/ChatProcessing.java @@ -145,7 +145,7 @@ public class ChatProcessing { DebugCommand.SendDebugMessage(jsonstr); try { - if (channel.filteranderrormsg != null) { + if (!channel.isGlobal()) { Objective obj = PluginMain.SB.getObjective(channel.ID); int score = -1; for (Player p : Bukkit.getOnlinePlayers()) { diff --git a/src/main/java/buttondevteam/chat/listener/PlayerListener.java b/src/main/java/buttondevteam/chat/listener/PlayerListener.java index 4997347..2304407 100644 --- a/src/main/java/buttondevteam/chat/listener/PlayerListener.java +++ b/src/main/java/buttondevteam/chat/listener/PlayerListener.java @@ -272,7 +272,7 @@ public class PlayerListener implements Listener { @EventHandler public void onChannelRegistered(ChatChannelRegisterEvent e) { - if (e.getChannel().filteranderrormsg != null && PluginMain.SB.getObjective(e.getChannel().ID) == null) // Not global chat and doesn't exist yet + if (!e.getChannel().isGlobal() && PluginMain.SB.getObjective(e.getChannel().ID) == null) // Not global chat and doesn't exist yet PluginMain.SB.registerNewObjective(e.getChannel().ID, "dummy"); } From cf8af73ed05f0ea71d34ae3c609411c343663ce6 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 24 Dec 2018 00:14:38 +0100 Subject: [PATCH 04/10] No players, no announcements Not broadcasting announcements if nobody is online (mainly because of Discord) --- src/main/java/buttondevteam/chat/AnnouncerThread.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/buttondevteam/chat/AnnouncerThread.java b/src/main/java/buttondevteam/chat/AnnouncerThread.java index b1b11da..60d40e7 100644 --- a/src/main/java/buttondevteam/chat/AnnouncerThread.java +++ b/src/main/java/buttondevteam/chat/AnnouncerThread.java @@ -13,6 +13,7 @@ public class AnnouncerThread implements Runnable { } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } + if (Bukkit.getOnlinePlayers().size() == 0) continue; //Don't post to Discord if nobody is on if (PluginMain.AnnounceMessages.size() > AnnounceMessageIndex) { Bukkit.broadcastMessage(PluginMain.AnnounceMessages.get(AnnounceMessageIndex)); AnnounceMessageIndex++; From f8539a03922b1a8c0189b5ab1c7f85812cf28106 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Wed, 26 Dec 2018 03:03:51 +0100 Subject: [PATCH 05/10] Adding chat history command #82 --- .../chat/commands/ucmds/HistoryCommand.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java diff --git a/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java b/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java new file mode 100644 index 0000000..c32401b --- /dev/null +++ b/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java @@ -0,0 +1,74 @@ +package buttondevteam.chat.commands.ucmds; + +import buttondevteam.lib.chat.Channel; +import buttondevteam.lib.chat.ChatMessage; +import buttondevteam.lib.chat.CommandClass; +import lombok.RequiredArgsConstructor; +import lombok.val; +import org.bukkit.command.CommandSender; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; +import java.util.stream.Stream; + +@CommandClass +public class HistoryCommand extends UCommandBase { + private static HashMap messages = new HashMap<>(); + + @Override + public String[] GetHelpText(String alias) { + return new String[]{ // + "§6--- Chat History ----", // + "Returns the last 10 messages the player can see." // + }; + } + + @Override + public boolean OnCommand(CommandSender sender, String alias, String[] args) { + Function, Map.Entry> filterThem = e -> { + int score = e.getKey().getMCScore(sender); + HistoryEntry[] he = new HistoryEntry[10]; + for (int i = 0, j = 0; i < 10; i++) { + val cm = e.getValue()[i].chatMessage; + if (cm == null) + break; //Don't have 10 messages yet + if (score == e.getKey().getMCScore(cm.getPermCheck())) + he[j++] = e.getValue()[i]; + } + return new HashMap.SimpleEntry<>(e.getKey(), he); + }; + sender.sendMessage("§6---- Chat History ----"); + Stream stream; + if (args.length == 0) { + stream = messages.entrySet().stream().map(filterThem).flatMap(e -> Arrays.stream(e.getValue())); + } else { + Channel ch = Channel.GlobalChat; //TODO: Channel param + val hes = messages.get(ch); + if (hes == null) + return true; + stream = Arrays.stream(hes); + } + AtomicBoolean sent = new AtomicBoolean(); + stream.sorted(Comparator.comparingLong(he -> he.timestamp)).forEach(e -> { + val cm = e.chatMessage; + sender.sendMessage(cm.getSender().getName() + ": " + cm.getMessage()); + sent.set(true); + }); + if (!sent.get()) + sender.sendMessage("No messages can be found."); + return true; + } + + @RequiredArgsConstructor + public static class HistoryEntry { + /** + * System.nanoTime() + */ + private final long timestamp; + private final ChatMessage chatMessage; + } +} From 1081f3cf9d00c236030fe7d47f8596db05a5533c Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 27 Dec 2018 00:02:47 +0100 Subject: [PATCH 06/10] Chat history works! Also fixed a lot Actually registered the join/leave listener, fixing town colors and nickname mentioning as well Chat history is finished, it only shows messages that the sender has access to #82 --- lombok.config | 1 + .../java/buttondevteam/chat/PluginMain.java | 2 + .../chat/commands/ucmds/HistoryCommand.java | 62 ++++++++++++------- .../listener/PlayerJoinLeaveListener.java | 7 ++- .../chat/listener/PlayerListener.java | 2 + 5 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 lombok.config diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..d959b09 --- /dev/null +++ b/lombok.config @@ -0,0 +1 @@ +lombok.var.flagUsage = ALLOW diff --git a/src/main/java/buttondevteam/chat/PluginMain.java b/src/main/java/buttondevteam/chat/PluginMain.java index 7ad1825..b02f678 100644 --- a/src/main/java/buttondevteam/chat/PluginMain.java +++ b/src/main/java/buttondevteam/chat/PluginMain.java @@ -2,6 +2,7 @@ package buttondevteam.chat; import buttondevteam.chat.commands.YeehawCommand; import buttondevteam.chat.commands.ucmds.TownColorCommand; +import buttondevteam.chat.listener.PlayerJoinLeaveListener; import buttondevteam.chat.listener.PlayerListener; import buttondevteam.chat.listener.TownyListener; import buttondevteam.lib.TBMCCoreAPI; @@ -81,6 +82,7 @@ public class PluginMain extends JavaPlugin { // Translated to Java: 2015.07.15. PluginMain.essentials = (Essentials) (Bukkit.getPluginManager().getPlugin("Essentials")); TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this); + TBMCCoreAPI.RegisterEventsForExceptions(new PlayerJoinLeaveListener(), this); TBMCCoreAPI.RegisterEventsForExceptions(new TownyListener(), this); TBMCChatAPI.AddCommands(this, YeehawCommand.class); Console = this.getServer().getConsoleSender(); diff --git a/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java b/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java index c32401b..8729986 100644 --- a/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java +++ b/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java @@ -4,20 +4,19 @@ import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.ChatMessage; import buttondevteam.lib.chat.CommandClass; import lombok.RequiredArgsConstructor; +import lombok.experimental.var; import lombok.val; import org.bukkit.command.CommandSender; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; +import javax.annotation.Nullable; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.stream.Stream; @CommandClass public class HistoryCommand extends UCommandBase { - private static HashMap messages = new HashMap<>(); + private static HashMap> messages = new HashMap<>(); @Override public String[] GetHelpText(String alias) { @@ -29,46 +28,65 @@ public class HistoryCommand extends UCommandBase { @Override public boolean OnCommand(CommandSender sender, String alias, String[] args) { - Function, Map.Entry> filterThem = e -> { + return showHistory(sender, alias, args, this); + } + + public static boolean showHistory(CommandSender sender, String alias, String[] args, @Nullable HistoryCommand hc) { + Function>, Map.Entry>> filterThem = e -> { int score = e.getKey().getMCScore(sender); - HistoryEntry[] he = new HistoryEntry[10]; - for (int i = 0, j = 0; i < 10; i++) { - val cm = e.getValue()[i].chatMessage; - if (cm == null) - break; //Don't have 10 messages yet + LinkedList he = new LinkedList<>(); + for (int i = 0; i < 10 && i < e.getValue().size(); i++) { + val heh = e.getValue().get(i); + val cm = heh.chatMessage; if (score == e.getKey().getMCScore(cm.getPermCheck())) - he[j++] = e.getValue()[i]; + he.push(heh); } return new HashMap.SimpleEntry<>(e.getKey(), he); }; sender.sendMessage("§6---- Chat History ----"); - Stream stream; + Stream>> stream; if (args.length == 0) { - stream = messages.entrySet().stream().map(filterThem).flatMap(e -> Arrays.stream(e.getValue())); + stream = messages.entrySet().stream(); } else { - Channel ch = Channel.GlobalChat; //TODO: Channel param - val hes = messages.get(ch); - if (hes == null) + Optional och = Channel.getChannels().stream().filter(chan -> chan.ID.equalsIgnoreCase(args[0])).findAny(); + if (!och.isPresent()) { + sender.sendMessage("§cChannel not found. Use the ID, for example: /" + (hc == null ? "u history" : hc.GetCommandPath()) + " ooc"); return true; - stream = Arrays.stream(hes); + } + val hes = messages.get(och.get()); + if (hes == null) + stream = Stream.empty(); + else + stream = Stream.of(new HashMap.SimpleEntry<>(och.get(), hes)); } AtomicBoolean sent = new AtomicBoolean(); - stream.sorted(Comparator.comparingLong(he -> he.timestamp)).forEach(e -> { + val arr = stream.map(filterThem).flatMap(e -> e.getValue().stream()) + .sorted(Comparator.comparingLong(he -> he.timestamp)).toArray(HistoryEntry[]::new); + for (int i = Math.max(0, arr.length - 10); i < arr.length; i++) { + HistoryEntry e = arr[i]; val cm = e.chatMessage; - sender.sendMessage(cm.getSender().getName() + ": " + cm.getMessage()); + sender.sendMessage("[" + e.channel.DisplayName + "] " + cm.getSender().getName() + ": " + cm.getMessage()); sent.set(true); - }); + } if (!sent.get()) sender.sendMessage("No messages can be found."); return true; } @RequiredArgsConstructor - public static class HistoryEntry { + private static class HistoryEntry { /** * System.nanoTime() */ private final long timestamp; private final ChatMessage chatMessage; + private final Channel channel; + } + + public static void addChatMessage(ChatMessage chatMessage, Channel channel) { + var ll = messages.computeIfAbsent(channel, k -> new LinkedList<>()); //<-- TIL + ll.add(new HistoryEntry(System.nanoTime(), chatMessage, channel)); //Adds as last element + while (ll.size() > 10) + ll.remove(); //Removes the first element } } diff --git a/src/main/java/buttondevteam/chat/listener/PlayerJoinLeaveListener.java b/src/main/java/buttondevteam/chat/listener/PlayerJoinLeaveListener.java index 0c57e7c..3a49a4a 100644 --- a/src/main/java/buttondevteam/chat/listener/PlayerJoinLeaveListener.java +++ b/src/main/java/buttondevteam/chat/listener/PlayerJoinLeaveListener.java @@ -5,6 +5,7 @@ import buttondevteam.chat.FlairStates; import buttondevteam.chat.PlayerJoinTimerTask; import buttondevteam.chat.PluginMain; import buttondevteam.chat.commands.UnlolCommand; +import buttondevteam.chat.commands.ucmds.HistoryCommand; import buttondevteam.lib.chat.Color; import buttondevteam.lib.player.TBMCPlayerJoinEvent; import buttondevteam.lib.player.TBMCPlayerLoadEvent; @@ -64,14 +65,14 @@ public class PlayerJoinLeaveListener implements Listener { nwithoutformatting = p.getName(); PlayerListener.nicknames.forcePut(nwithoutformatting.toLowerCase(), p.getUniqueId()); - Bukkit.getScheduler().runTaskLater(PluginMain.Instance, () -> { - updatePlayerColors(p, cp); //TODO: Doesn't have effect - }, 5); + updatePlayerColors(p, cp); //TO!DO: Doesn't have effect - It can help to register the listener if (cp.ChatOnly || p.getGameMode().equals(GameMode.SPECTATOR)) { cp.ChatOnly = false; p.setGameMode(GameMode.SURVIVAL); } + + HistoryCommand.showHistory(e.getPlayer(), "u history", new String[0], null); } @EventHandler diff --git a/src/main/java/buttondevteam/chat/listener/PlayerListener.java b/src/main/java/buttondevteam/chat/listener/PlayerListener.java index 2304407..fd8dfb5 100644 --- a/src/main/java/buttondevteam/chat/listener/PlayerListener.java +++ b/src/main/java/buttondevteam/chat/listener/PlayerListener.java @@ -3,6 +3,7 @@ package buttondevteam.chat.listener; import buttondevteam.chat.ChatPlayer; import buttondevteam.chat.ChatProcessing; import buttondevteam.chat.PluginMain; +import buttondevteam.chat.commands.ucmds.HistoryCommand; import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.chat.*; @@ -258,6 +259,7 @@ public class PlayerListener implements Listener { try { if (e.isCancelled()) return; + HistoryCommand.addChatMessage(e.getCm(), e.getChannel()); e.setCancelled(ChatProcessing.ProcessChat(e)); } catch (NoClassDefFoundError | Exception ex) { // Weird things can happen for (Player p : Bukkit.getOnlinePlayers()) From 12072f310650f079926a54c71b4565302d5ca01f Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Thu, 27 Dec 2018 14:16:40 +0100 Subject: [PATCH 07/10] 9 less lines for what works better Storing the entries per-group which also means there's no need to loop through each entry - and it won't limit it globally --- .../chat/commands/ucmds/HistoryCommand.java | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java b/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java index 8729986..e39600a 100644 --- a/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java +++ b/src/main/java/buttondevteam/chat/commands/ucmds/HistoryCommand.java @@ -16,7 +16,10 @@ import java.util.stream.Stream; @CommandClass public class HistoryCommand extends UCommandBase { - private static HashMap> messages = new HashMap<>(); + /** + * Key: ChannelID_groupID + */ + private static HashMap> messages = new HashMap<>(); @Override public String[] GetHelpText(String alias) { @@ -32,35 +35,21 @@ public class HistoryCommand extends UCommandBase { } public static boolean showHistory(CommandSender sender, String alias, String[] args, @Nullable HistoryCommand hc) { - Function>, Map.Entry>> filterThem = e -> { - int score = e.getKey().getMCScore(sender); - LinkedList he = new LinkedList<>(); - for (int i = 0; i < 10 && i < e.getValue().size(); i++) { - val heh = e.getValue().get(i); - val cm = heh.chatMessage; - if (score == e.getKey().getMCScore(cm.getPermCheck())) - he.push(heh); - } - return new HashMap.SimpleEntry<>(e.getKey(), he); - }; + Function> getThem = ch -> messages.get(ch.ID + "_" + ch.getGroupID(sender)); //If can't see, groupID is null, and that shouldn't be in the map sender.sendMessage("§6---- Chat History ----"); - Stream>> stream; + Stream stream; if (args.length == 0) { - stream = messages.entrySet().stream(); + stream = Channel.getChannels().stream(); } else { Optional och = Channel.getChannels().stream().filter(chan -> chan.ID.equalsIgnoreCase(args[0])).findAny(); if (!och.isPresent()) { sender.sendMessage("§cChannel not found. Use the ID, for example: /" + (hc == null ? "u history" : hc.GetCommandPath()) + " ooc"); return true; } - val hes = messages.get(och.get()); - if (hes == null) - stream = Stream.empty(); - else - stream = Stream.of(new HashMap.SimpleEntry<>(och.get(), hes)); + stream = Stream.of(och.get()); } AtomicBoolean sent = new AtomicBoolean(); - val arr = stream.map(filterThem).flatMap(e -> e.getValue().stream()) + val arr = stream.map(getThem).filter(Objects::nonNull).flatMap(Collection::stream) .sorted(Comparator.comparingLong(he -> he.timestamp)).toArray(HistoryEntry[]::new); for (int i = Math.max(0, arr.length - 10); i < arr.length; i++) { HistoryEntry e = arr[i]; @@ -84,7 +73,9 @@ public class HistoryCommand extends UCommandBase { } public static void addChatMessage(ChatMessage chatMessage, Channel channel) { - var ll = messages.computeIfAbsent(channel, k -> new LinkedList<>()); //<-- TIL + val groupID = channel.getGroupID(chatMessage.getPermCheck()); + if (groupID == null) return; //Just to be sure + var ll = messages.computeIfAbsent(channel.ID + "_" + groupID, k -> new LinkedList<>()); //<-- TIL ll.add(new HistoryEntry(System.nanoTime(), chatMessage, channel)); //Adds as last element while (ll.size() > 10) ll.remove(); //Removes the first element From 99a8c1b02027af0b59dc9b1687bf04099718ce6c Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Fri, 28 Dec 2018 00:55:32 +0100 Subject: [PATCH 08/10] Fixed nicknames if only 1 player is on Also added a town colors component class --- .../buttondevteam/chat/ChatProcessing.java | 5 ++-- .../chat/components/TownColorComponent.java | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/main/java/buttondevteam/chat/components/TownColorComponent.java diff --git a/src/main/java/buttondevteam/chat/ChatProcessing.java b/src/main/java/buttondevteam/chat/ChatProcessing.java index 02fe85c..e9e65be 100644 --- a/src/main/java/buttondevteam/chat/ChatProcessing.java +++ b/src/main/java/buttondevteam/chat/ChatProcessing.java @@ -263,10 +263,9 @@ public class ChatProcessing { final String nick = PlayerListener.nicknames.inverse().get(p.getUniqueId()); if (nick != null) { nicksb.append(nick); - if (index < size - 1) { + if (index < size - 1) nicksb.append("|"); - addNickFormatter = true; - } + addNickFormatter = true; //Add it even if there's only 1 player online (it was in the if) } index++; } diff --git a/src/main/java/buttondevteam/chat/components/TownColorComponent.java b/src/main/java/buttondevteam/chat/components/TownColorComponent.java new file mode 100644 index 0000000..b731ea7 --- /dev/null +++ b/src/main/java/buttondevteam/chat/components/TownColorComponent.java @@ -0,0 +1,24 @@ +package buttondevteam.chat.components; + +import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.architecture.ConfigData; + +public class TownColorComponent extends Component { + public ConfigData colorCount() { //TODO + return getData("colorCount", (byte) 1, cc -> (byte) cc, cc -> (int) cc); + } + + public ConfigData useNationColors() { //TODO + return getData("useNationColors", true); + } + + @Override + protected void enable() { + //TODO: Don't register all commands automatically (welp) + } + + @Override + protected void disable() { + + } +} From 720740dea358c18c2ea3e13861f99a31679225f6 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 1 Jan 2019 03:28:46 +0100 Subject: [PATCH 09/10] Fixed URL processing (&, #) New Years Commit --- src/main/java/buttondevteam/chat/ChatProcessing.java | 2 +- src/test/java/buttondevteam/chat/ChatFormatIT.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/buttondevteam/chat/ChatProcessing.java b/src/main/java/buttondevteam/chat/ChatProcessing.java index e9e65be..c86bf05 100644 --- a/src/main/java/buttondevteam/chat/ChatProcessing.java +++ b/src/main/java/buttondevteam/chat/ChatProcessing.java @@ -40,7 +40,7 @@ public class ChatProcessing { 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 URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)"); public static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+"); private static final Pattern UNDERLINED_PATTERN = Pattern.compile("_"); private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*"); diff --git a/src/test/java/buttondevteam/chat/ChatFormatIT.java b/src/test/java/buttondevteam/chat/ChatFormatIT.java index 7929b4f..bb508cc 100644 --- a/src/test/java/buttondevteam/chat/ChatFormatIT.java +++ b/src/test/java/buttondevteam/chat/ChatFormatIT.java @@ -65,6 +65,11 @@ public class ChatFormatIT { .setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/")), new TellrawPart(" heh").setItalic(true))); list.add(new ChatFormatIT(sender, "*test _test_ test*", new TellrawPart("test ").setItalic(true).setColor(Color.White), new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White))); + list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/test?test&test#test", new TellrawPart("https://norbipeti.github.io/test?test&test#test") + .setColor(Color.White).setUnderlined(true) + .setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, + new TellrawPart("Click to open").setColor(Color.Blue))) + .setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test?test&test#test")))); return list; } From aed7864a15874798bdf36142472b75a01b3b22a2 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Wed, 2 Jan 2019 23:30:46 +0100 Subject: [PATCH 10/10] Fix nickname regex bug The previous implementation didn't consider tbe case when the last player in the list doesn't have a nickname, leaving an empty "always match" part which messed up the formatting @FigyTuna Also added editorconfig for GitHub formatting --- .editorconfig | 19 + .../buttondevteam/chat/ChatProcessing.java | 692 +++++++++--------- 2 files changed, 364 insertions(+), 347 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4b9e6ec --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = false +indent_style = space +indent_size = 4 + +[*.json] +indent_style = space +indent_size = 2 + +[*.java] +indent_style = tab +tab_width = 4 + +[{*.yml, *.yaml}] +indent_style = space +indent_size = 2 + diff --git a/src/main/java/buttondevteam/chat/ChatProcessing.java b/src/main/java/buttondevteam/chat/ChatProcessing.java index c86bf05..77d1f03 100644 --- a/src/main/java/buttondevteam/chat/ChatProcessing.java +++ b/src/main/java/buttondevteam/chat/ChatProcessing.java @@ -1,347 +1,345 @@ -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.Channel; -import buttondevteam.lib.chat.Color; -import buttondevteam.lib.chat.Priority; -import buttondevteam.lib.chat.TellrawSerializableEnum; -import buttondevteam.lib.player.ChromaGamerBase; -import buttondevteam.lib.player.TBMCPlayer; -import buttondevteam.lib.player.TBMCPlayerBase; -import com.earth2me.essentials.User; -import com.google.common.collect.Lists; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import lombok.val; -import org.bukkit.Bukkit; -import org.bukkit.Sound; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.scoreboard.Objective; - -import javax.annotation.Nullable; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import java.util.regex.Pattern; - -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:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)"); - public 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 Pattern STRIKETHROUGH_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; - - 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).type(ChatFormatter.Type.Range) - .priority(Priority.High).build(), - ChatFormatter.builder().regex(ITALIC_PATTERN).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(), - ChatFormatter.builder().regex(UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range) - .build(), - ChatFormatter.builder().regex(STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range) - .build(), - ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).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).type(ChatFormatter.Type.Range) - .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 static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"}; - static final String MCORIGIN = "Minecraft"; //Shouldn't change, like ever - TBMCPlayer.getFolderForType(TBMCPlayer.class) capitalized - - private ChatProcessing() { - } - - public static boolean ProcessChat(TBMCChatEvent e) { - Channel channel = e.getChannel(); - CommandSender sender = e.getSender(); - String message = e.getMessage(); - long processstart = System.nanoTime(); - Player player = (sender instanceof Player ? (Player) sender : null); - User user = PluginMain.essentials.getUser(player); - - if (player != null) { - user.updateActivity(true); //Could talk in a private channel, so broadcast - if (user.isMuted()) - return true; - } - - doFunStuff(sender, e, message); - - ChatPlayer mp; - if (player != null) - mp = TBMCPlayerBase.getPlayer(player.getUniqueId(), ChatPlayer.class); - else //Due to the online player map, getPlayer() can be more efficient than getAs() - mp = e.getUser().getAs(ChatPlayer.class); //May be null - - 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, e.getOrigin()); - - TellrawPart json = createTellraw(sender, message, player, mp, e.getUser(), channelidentifier, e.getOrigin()); - 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.isGlobal()) { - 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) { - return gson.toJson(json); - } - - static TellrawPart createTellraw(CommandSender sender, String message, @Nullable Player player, - @Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier, - String origin) { - 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((MCORIGIN.equals(origin) ? "" : "From " + origin + "n") - + "Copy message").setColor(Color.Blue))) - .setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND, message))); - if (PluginMain.permission.has(sender, "tbmc.badge.diamond")) - json.addExtra(new TellrawPart("[P]").setColor(Color.Aqua).setBold(true) - .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Diamond Patreon supporter"))); - else if (PluginMain.permission.has(sender, "tbmc.badge.gold")) - json.addExtra(new TellrawPart("[P]").setColor(Color.Gold).setBold(true) - .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Gold Patreon supporter"))); - json.addExtra(new TellrawPart(" <")); - TellrawPart hovertp = new TellrawPart(""); - if (cg != null) - hovertp.addExtra(new TellrawPart(cg.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(); - return player.getDisplayName(); - } - - static String getChannelID(Channel channel, CommandSender sender, String origin) { - return ("[" + (MCORIGIN.equals(origin) ? "" : "§8" + origin.substring(0, 1) + "§r|") + channel.DisplayName) - + "]"; - } - - 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()); - - boolean nottest; //Not assigning a default value, so that it can only be used in the if - if ((nottest = Bukkit.getOnlinePlayers().size() > 0) || Bukkit.getVersion().equals("test")) { - StringBuilder namesb = new StringBuilder("(?i)("); - if (nottest) - for (Player p : Bukkit.getOnlinePlayers()) - namesb.append(p.getName()).append("|"); - else - for (String testPlayer : testPlayers) - namesb.append(testPlayer).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; //Add it even if there's only 1 player online (it was in the if) - } - index++; - } - nicksb.append(")"); - - Consumer error = message -> { - if (PluginMain.Instance != null) - PluginMain.Instance.getLogger().warning(message); - else - System.out.println(message); - }; - - formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua) - .onmatch((match, builder) -> { - Player p = Bukkit.getPlayer(match); - Optional pn = nottest ? Optional.empty() - : Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny(); - if (nottest ? p == null : !pn.isPresent()) { - error.accept("Error: Can't find player " + match + " but was reported as online."); - return "§c" + match + "§r"; - } - ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class); - if (nottest) { - 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 + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing - }).priority(Priority.High).type(ChatFormatter.Type.Excluder).build()); - - if (addNickFormatter) - formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua) - .onmatch((match, builder) -> { - if (PlayerListener.nicknames.containsKey(match.toLowerCase())) { //Made a stream and all that but I can actually store it lowercased - Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match.toLowerCase())); - if (p == null) { - error.accept("Error: Can't find player nicknamed " - + match.toLowerCase() + " 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(); - } - error.accept("Player nicknamed " + match.toLowerCase() - + " not found in nickname map but was reported as online."); - return "§c" + match + "§r"; - }).priority(Priority.High).type(ChatFormatter.Type.Excluder).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); - - 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); - } -} +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.Channel; +import buttondevteam.lib.chat.Color; +import buttondevteam.lib.chat.Priority; +import buttondevteam.lib.chat.TellrawSerializableEnum; +import buttondevteam.lib.player.ChromaGamerBase; +import buttondevteam.lib.player.TBMCPlayer; +import buttondevteam.lib.player.TBMCPlayerBase; +import com.earth2me.essentials.User; +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.val; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Objective; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.regex.Pattern; + +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:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)"); + public 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 Pattern STRIKETHROUGH_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; + + 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).type(ChatFormatter.Type.Range) + .priority(Priority.High).build(), + ChatFormatter.builder().regex(ITALIC_PATTERN).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(), + ChatFormatter.builder().regex(UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range) + .build(), + ChatFormatter.builder().regex(STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range) + .build(), + ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).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).type(ChatFormatter.Type.Range) + .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 static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"}; + static final String MCORIGIN = "Minecraft"; //Shouldn't change, like ever - TBMCPlayer.getFolderForType(TBMCPlayer.class) capitalized + + private ChatProcessing() { + } + + public static boolean ProcessChat(TBMCChatEvent e) { + Channel channel = e.getChannel(); + CommandSender sender = e.getSender(); + String message = e.getMessage(); + long processstart = System.nanoTime(); + Player player = (sender instanceof Player ? (Player) sender : null); + User user = PluginMain.essentials.getUser(player); + + if (player != null) { + user.updateActivity(true); //Could talk in a private channel, so broadcast + if (user.isMuted()) + return true; + } + + doFunStuff(sender, e, message); + + ChatPlayer mp; + if (player != null) + mp = TBMCPlayerBase.getPlayer(player.getUniqueId(), ChatPlayer.class); + else //Due to the online player map, getPlayer() can be more efficient than getAs() + mp = e.getUser().getAs(ChatPlayer.class); //May be null + + 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, e.getOrigin()); + + TellrawPart json = createTellraw(sender, message, player, mp, e.getUser(), channelidentifier, e.getOrigin()); + 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.isGlobal()) { + 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) { + return gson.toJson(json); + } + + static TellrawPart createTellraw(CommandSender sender, String message, @Nullable Player player, + @Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier, + String origin) { + 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((MCORIGIN.equals(origin) ? "" : "From " + origin + "n") + + "Copy message").setColor(Color.Blue))) + .setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND, message))); + if (PluginMain.permission.has(sender, "tbmc.badge.diamond")) + json.addExtra(new TellrawPart("[P]").setColor(Color.Aqua).setBold(true) + .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Diamond Patreon supporter"))); + else if (PluginMain.permission.has(sender, "tbmc.badge.gold")) + json.addExtra(new TellrawPart("[P]").setColor(Color.Gold).setBold(true) + .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Gold Patreon supporter"))); + json.addExtra(new TellrawPart(" <")); + TellrawPart hovertp = new TellrawPart(""); + if (cg != null) + hovertp.addExtra(new TellrawPart(cg.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(); + return player.getDisplayName(); + } + + static String getChannelID(Channel channel, CommandSender sender, String origin) { + return ("[" + (MCORIGIN.equals(origin) ? "" : "§8" + origin.substring(0, 1) + "§r|") + channel.DisplayName) + + "]"; + } + + 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()); + + boolean nottest; //Not assigning a default value, so that it can only be used in the if + if ((nottest = Bukkit.getOnlinePlayers().size() > 0) || Bukkit.getVersion().equals("test")) { + StringBuilder namesb = new StringBuilder("(?i)("); + if (nottest) + for (Player p : Bukkit.getOnlinePlayers()) + namesb.append(p.getName()).append("|"); + else + for (String testPlayer : testPlayers) + namesb.append(testPlayer).append("|"); + namesb.deleteCharAt(namesb.length() - 1); + namesb.append(")"); + StringBuilder nicksb = new StringBuilder("(?i)("); + boolean addNickFormatter = false; + int index = 0; + for (Player p : Bukkit.getOnlinePlayers()) { + final String nick = PlayerListener.nicknames.inverse().get(p.getUniqueId()); + if (nick != null) { + nicksb.append(nick).append("|"); + addNickFormatter = true; //Add it even if there's only 1 player online (it was in the if) + } + index++; + } + nicksb.deleteCharAt(nicksb.length() - 1); + nicksb.append(")"); + + Consumer error = message -> { + if (PluginMain.Instance != null) + PluginMain.Instance.getLogger().warning(message); + else + System.out.println(message); + }; + + formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua) + .onmatch((match, builder) -> { + Player p = Bukkit.getPlayer(match); + Optional pn = nottest ? Optional.empty() + : Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny(); + if (nottest ? p == null : !pn.isPresent()) { + error.accept("Error: Can't find player " + match + " but was reported as online."); + return "§c" + match + "§r"; + } + ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class); + if (nottest) { + 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 + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing + }).priority(Priority.High).type(ChatFormatter.Type.Excluder).build()); + + if (addNickFormatter) + formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua) + .onmatch((match, builder) -> { + if (PlayerListener.nicknames.containsKey(match.toLowerCase())) { //Made a stream and all that but I can actually store it lowercased + Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match.toLowerCase())); + if (p == null) { + error.accept("Error: Can't find player nicknamed " + + match.toLowerCase() + " 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(); + } + error.accept("Player nicknamed " + match.toLowerCase() + + " not found in nickname map but was reported as online."); + return "§c" + match + "§r"; + }).priority(Priority.High).type(ChatFormatter.Type.Excluder).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); + + 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); + } +}