Fully implement previews and refactor legacy handling

This commit is contained in:
MD 2022-08-02 20:17:34 +01:00
parent 7e01f912e5
commit a0eba932d5
11 changed files with 192 additions and 405 deletions

View File

@ -314,6 +314,7 @@ enderchestCommandUsage2=/<command> <player>
enderchestCommandUsage2Description=Opens the ender chest of the target player
errorCallingCommand=Error calling the command /{0}
errorWithMessage=\u00a7cError\:\u00a74 {0}
essChatNoSecureMsg=EssentialsX Chat version {0} does not support secure chat on this server software. Update EssentialsX, and if this issue persists, inform the developers.
essentialsCommandDescription=Reloads essentials.
essentialsCommandUsage=/<command>
essentialsCommandUsage1=/<command> reload

View File

@ -1,42 +0,0 @@
package com.earth2me.essentials.chat;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
class ChatStore {
private final User user;
private final String type;
private final Trade charge;
private long radius;
ChatStore(final IEssentials ess, final User user, final String type) {
this.user = user;
this.type = type;
this.charge = new Trade(getLongType(), ess);
}
User getUser() {
return user;
}
Trade getCharge() {
return charge;
}
String getType() {
return type;
}
final String getLongType() {
return type.length() == 0 ? "chat" : "chat-" + type;
}
long getRadius() {
return radius;
}
void setRadius(final long radius) {
this.radius = radius;
}
}

View File

@ -1,17 +1,16 @@
package com.earth2me.essentials.chat;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.EssentialsLogger;
import com.earth2me.essentials.chat.processing.LegacyChatHandler;
import com.earth2me.essentials.chat.processing.SignedChatHandler;
import com.earth2me.essentials.metrics.MetricsWrapper;
import net.ess3.api.IEssentials;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tl;
@ -33,14 +32,13 @@ public class EssentialsChat extends JavaPlugin {
return;
}
final Map<AsyncPlayerChatEvent, ChatStore> chatStore = Collections.synchronizedMap(new HashMap<>());
final EssentialsChatPlayerListenerLowest playerListenerLowest = new EssentialsChatPlayerListenerLowest(getServer(), ess, this, chatStore);
final EssentialsChatPlayerListenerNormal playerListenerNormal = new EssentialsChatPlayerListenerNormal(getServer(), ess, this, chatStore);
final EssentialsChatPlayerListenerHighest playerListenerHighest = new EssentialsChatPlayerListenerHighest(getServer(), ess, this, chatStore);
pluginManager.registerEvents(playerListenerLowest, this);
pluginManager.registerEvents(playerListenerNormal, this);
pluginManager.registerEvents(playerListenerHighest, this);
final SignedChatHandler signedHandler = new SignedChatHandler((Essentials) ess, this);
if (signedHandler.tryRegisterListeners()) {
getLogger().info("Secure signed chat and previews are enabled.");
} else {
final LegacyChatHandler legacyHandler = new LegacyChatHandler((Essentials) ess, this);
legacyHandler.registerListeners();
}
if (metrics == null) {
metrics = new MetricsWrapper(this, 3814, false);

View File

@ -1,79 +0,0 @@
package com.earth2me.essentials.chat;
import com.earth2me.essentials.ChargeException;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import org.bukkit.Server;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.Map;
public abstract class EssentialsChatPlayer implements Listener {
final transient IEssentials ess;
final transient EssentialsChat essChat;
final transient Server server;
private final transient Map<AsyncPlayerChatEvent, ChatStore> chatStorage;
EssentialsChatPlayer(final Server server, final IEssentials ess, final EssentialsChat essChat, final Map<AsyncPlayerChatEvent, ChatStore> chatStorage) {
this.ess = ess;
this.essChat = essChat;
this.server = server;
this.chatStorage = chatStorage;
}
public abstract void onPlayerChat(final AsyncPlayerChatEvent event);
boolean isAborted(final AsyncPlayerChatEvent event) {
return event.isCancelled();
}
String getChatType(final User user, final String message) {
if (message.length() == 0) {
//Ignore empty chat events generated by plugins
return "";
}
final char prefix = message.charAt(0);
if (prefix == ess.getSettings().getChatShout()) {
if (user.isToggleShout()) {
return "";
}
return message.length() > 1 ? "shout" : "";
} else if (ess.getSettings().isChatQuestionEnabled() && prefix == ess.getSettings().getChatQuestion()) {
return message.length() > 1 ? "question" : "";
} else if (user.isToggleShout()) {
return message.length() > 1 ? "shout" : "";
} else {
return "";
}
}
ChatStore getChatStore(final AsyncPlayerChatEvent event) {
return chatStorage.get(event);
}
void setChatStore(final AsyncPlayerChatEvent event, final ChatStore chatStore) {
chatStorage.put(event, chatStore);
}
ChatStore delChatStore(final AsyncPlayerChatEvent event) {
return chatStorage.remove(event);
}
private void charge(final User user, final Trade charge) throws ChargeException {
charge.charge(user);
}
boolean charge(final AsyncPlayerChatEvent event, final ChatStore chatStore) {
try {
charge(chatStore.getUser(), chatStore.getCharge());
} catch (final ChargeException e) {
ess.showError(chatStore.getUser().getSource(), e, "\\ chat " + chatStore.getLongType());
event.setCancelled(true);
return false;
}
return true;
}
}

View File

@ -1,27 +0,0 @@
package com.earth2me.essentials.chat;
import net.ess3.api.IEssentials;
import org.bukkit.Server;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.Map;
public class EssentialsChatPlayerListenerHighest extends EssentialsChatPlayer {
EssentialsChatPlayerListenerHighest(final Server server, final IEssentials ess, final EssentialsChat essChat, final Map<AsyncPlayerChatEvent, ChatStore> chatStorage) {
super(server, ess, essChat, chatStorage);
}
@EventHandler(priority = EventPriority.HIGHEST)
@Override
public void onPlayerChat(final AsyncPlayerChatEvent event) {
final ChatStore chatStore = delChatStore(event);
if (isAborted(event) || chatStore == null) {
return;
}
// This file should handle charging the user for the action before returning control back
charge(event, chatStore);
}
}

View File

@ -1,72 +0,0 @@
package com.earth2me.essentials.chat;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import net.ess3.api.IEssentials;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.scoreboard.Team;
import java.util.Locale;
import java.util.Map;
public class EssentialsChatPlayerListenerLowest extends EssentialsChatPlayer {
EssentialsChatPlayerListenerLowest(final Server server, final IEssentials ess, final EssentialsChat essChat, final Map<AsyncPlayerChatEvent, ChatStore> chatStorage) {
super(server, ess, essChat, chatStorage);
}
@EventHandler(priority = EventPriority.LOWEST)
@Override
public void onPlayerChat(final AsyncPlayerChatEvent event) {
if (isAborted(event)) {
return;
}
final User user = ess.getUser(event.getPlayer());
if (user == null) {
event.setCancelled(true);
return;
}
final ChatStore chatStore = new ChatStore(ess, user, getChatType(user, event.getMessage()));
setChatStore(event, chatStore);
// This listener should apply the general chat formatting only...then return control back the event handler
event.setMessage(FormatUtil.formatMessage(user, "essentials.chat", event.getMessage()));
if (ChatColor.stripColor(event.getMessage()).length() == 0) {
event.setCancelled(true);
return;
}
final String group = user.getGroup();
final String world = user.getWorld().getName();
final String username = user.getName();
final String nickname = user.getFormattedNickname();
final Player player = user.getBase();
final String prefix = FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(player));
final String suffix = FormatUtil.replaceFormat(ess.getPermissionsHandler().getSuffix(player));
final Team team = player.getScoreboard().getPlayerTeam(player);
String format = ess.getSettings().getChatFormat(group);
format = format.replace("{0}", group);
format = format.replace("{1}", ess.getSettings().getWorldAlias(world));
format = format.replace("{2}", world.substring(0, 1).toUpperCase(Locale.ENGLISH));
format = format.replace("{3}", team == null ? "" : team.getPrefix());
format = format.replace("{4}", team == null ? "" : team.getSuffix());
format = format.replace("{5}", team == null ? "" : team.getDisplayName());
format = format.replace("{6}", prefix);
format = format.replace("{7}", suffix);
format = format.replace("{8}", username);
format = format.replace("{9}", nickname == null ? username : nickname);
synchronized (format) {
event.setFormat(format);
}
}
}

View File

@ -1,136 +0,0 @@
package com.earth2me.essentials.chat;
import com.earth2me.essentials.User;
import net.ess3.api.IEssentials;
import net.ess3.api.events.LocalChatSpyEvent;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import static com.earth2me.essentials.I18n.tl;
public class EssentialsChatPlayerListenerNormal extends EssentialsChatPlayer {
EssentialsChatPlayerListenerNormal(final Server server, final IEssentials ess, final EssentialsChat essChat, final Map<AsyncPlayerChatEvent, ChatStore> chatStorage) {
super(server, ess, essChat, chatStorage);
}
@EventHandler(priority = EventPriority.NORMAL)
@Override
public void onPlayerChat(final AsyncPlayerChatEvent event) {
if (isAborted(event)) {
return;
}
// This file should handle detection of the local chat features; if local chat is enabled, we need to handle it here
long radius = ess.getSettings().getChatRadius();
if (radius < 1) {
return;
}
radius *= radius;
final ChatStore chatStore = getChatStore(event);
final User user = chatStore.getUser();
chatStore.setRadius(radius);
if (event.getMessage().length() > 1) {
if (chatStore.getType().isEmpty()) {
if (!user.isAuthorized("essentials.chat.local")) {
user.sendMessage(tl("notAllowedToLocal"));
event.setCancelled(true);
return;
}
if (user.isToggleShout() && event.getMessage().length() > 1 && event.getMessage().charAt(0) == ess.getSettings().getChatShout()) {
event.setMessage(event.getMessage().substring(1));
}
event.getRecipients().removeIf(player -> !ess.getUser(player).isAuthorized("essentials.chat.receive.local"));
} else {
final String permission = "essentials.chat." + chatStore.getType();
if (user.isAuthorized(permission)) {
if (event.getMessage().charAt(0) == ess.getSettings().getChatShout() || (event.getMessage().charAt(0) == ess.getSettings().getChatQuestion() && ess.getSettings().isChatQuestionEnabled())) {
event.setMessage(event.getMessage().substring(1));
}
event.setFormat(tl(chatStore.getType() + "Format", event.getFormat()));
event.getRecipients().removeIf(player -> !ess.getUser(player).isAuthorized("essentials.chat.receive." + chatStore.getType()));
return;
}
user.sendMessage(tl("notAllowedTo" + chatStore.getType().substring(0, 1).toUpperCase(Locale.ENGLISH) + chatStore.getType().substring(1)));
event.setCancelled(true);
return;
}
}
final Location loc = user.getLocation();
final World world = loc.getWorld();
if (!charge(event, chatStore)) {
return;
}
final Set<Player> outList = event.getRecipients();
final Set<Player> spyList = new HashSet<>();
try {
outList.add(event.getPlayer());
} catch (final UnsupportedOperationException ex) {
if (ess.getSettings().isDebug()) {
essChat.getLogger().log(Level.INFO, "Plugin triggered custom chat event, local chat handling aborted.", ex);
}
return;
}
final String format = event.getFormat();
event.setFormat(tl("chatTypeLocal").concat(event.getFormat()));
final Iterator<Player> it = outList.iterator();
while (it.hasNext()) {
final Player onlinePlayer = it.next();
final User onlineUser = ess.getUser(onlinePlayer);
if (!onlineUser.equals(user)) {
boolean abort = false;
final Location playerLoc = onlineUser.getLocation();
if (playerLoc.getWorld() != world) {
abort = true;
} else {
final double delta = playerLoc.distanceSquared(loc);
if (delta > chatStore.getRadius()) {
abort = true;
}
}
if (abort) {
if (onlineUser.isAuthorized("essentials.chat.spy")) {
spyList.add(onlinePlayer);
}
it.remove();
}
}
}
if (outList.size() < 2) {
user.sendMessage(tl("localNoOne"));
}
final LocalChatSpyEvent spyEvent = new LocalChatSpyEvent(event.isAsynchronous(), event.getPlayer(), format, event.getMessage(), spyList);
server.getPluginManager().callEvent(spyEvent);
if (!spyEvent.isCancelled()) {
for (final Player onlinePlayer : spyEvent.getRecipients()) {
onlinePlayer.sendMessage(String.format(spyEvent.getFormat(), user.getDisplayName(), spyEvent.getMessage()));
}
}
}
}

View File

@ -29,7 +29,7 @@ public abstract class AbstractChatHandler {
protected final Essentials ess;
protected final EssentialsChat essChat;
protected final Server server;
private final ChatProcessingCache cache;
protected final ChatProcessingCache cache;
protected AbstractChatHandler(Essentials ess, EssentialsChat essChat) {
this.ess = ess;
@ -87,7 +87,8 @@ public abstract class AbstractChatHandler {
event.setFormat(format);
}
chat.setModifiedMessage(String.format(format, player.getDisplayName(), event.getMessage()));
chat.setFormatResult(format);
chat.setMessageResult(event.getMessage());
}
// Local chat recipients logic, handled at NORMAL level
@ -103,9 +104,8 @@ public abstract class AbstractChatHandler {
}
radius *= radius;
final ChatProcessingCache.IntermediateChat chatStore = cache.getIntermediateChat(event.getPlayer());
final ChatProcessingCache.Chat chatStore = cache.getIntermediateOrElseProcessedChat(event.getPlayer());
final User user = chatStore.getUser();
chatStore.setRadius(radius);
if (event.getMessage().length() > 1) {
if (chatStore.getType().isEmpty()) {
@ -124,6 +124,7 @@ public abstract class AbstractChatHandler {
final String permission = "essentials.chat." + chatStore.getType();
if (user.isAuthorized(permission)) {
// TODO: move this formatting over to handleChatFormat to avoid breaking signing
if (event.getMessage().charAt(0) == ess.getSettings().getChatShout() || (event.getMessage().charAt(0) == ess.getSettings().getChatQuestion() && ess.getSettings().isChatQuestionEnabled())) {
event.setMessage(event.getMessage().substring(1));
}
@ -141,11 +142,6 @@ public abstract class AbstractChatHandler {
final Location loc = user.getLocation();
final World world = loc.getWorld();
// TODO: why here, why again in highest? who did this? why? pay for your crimes
if (!charge(event, chatStore)) {
return;
}
final Set<Player> outList = event.getRecipients();
final Set<Player> spyList = new HashSet<>();
@ -172,7 +168,7 @@ public abstract class AbstractChatHandler {
abort = true;
} else {
final double delta = playerLoc.distanceSquared(loc);
if (delta > chatStore.getRadius()) {
if (delta > radius) {
abort = true;
}
}
@ -199,13 +195,17 @@ public abstract class AbstractChatHandler {
}
}
// Finalising the intermediate stages of chat processing, handled at HIGHEST level
protected void handleChatComplete(AsyncPlayerChatEvent event) {
// Finalising the intermediate stages of chat processing, handled at HIGHEST level during previews
protected void handleChatPostFormat(AsyncPlayerChatEvent event) {
final ChatProcessingCache.IntermediateChat intermediateChat = cache.clearIntermediateChat(event.getPlayer());
if (isAborted(event) || intermediateChat == null) {
return;
}
// in case of modifications by other plugins during the preview
intermediateChat.setFormatResult(event.getFormat());
intermediateChat.setMessageResult(event.getMessage());
final ChatProcessingCache.ProcessedChat processed = new ChatProcessingCache.ProcessedChat(ess, intermediateChat);
cache.setProcessedChat(event.getPlayer(), processed);
}
@ -217,6 +217,8 @@ public abstract class AbstractChatHandler {
// This file should handle charging the user for the action before returning control back
charge(event, cache.getProcessedChat(event.getPlayer()));
cache.clearProcessedChat(event.getPlayer());
}
boolean isAborted(final AsyncPlayerChatEvent event) {
@ -260,6 +262,7 @@ public abstract class AbstractChatHandler {
}
protected interface ChatListener extends Listener {
@SuppressWarnings("unused")
void onPlayerChat(AsyncPlayerChatEvent event);
}

View File

@ -20,26 +20,40 @@ public class ChatProcessingCache {
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
public IntermediateChat getIntermediateChat(Player player) {
public IntermediateChat getIntermediateChat(final Player player) {
return intermediateChats.get(player);
}
public void setIntermediateChat(Player player, IntermediateChat intermediateChat) {
public void setIntermediateChat(final Player player, final IntermediateChat intermediateChat) {
intermediateChats.put(player, intermediateChat);
}
public IntermediateChat clearIntermediateChat(Player player) {
public IntermediateChat clearIntermediateChat(final Player player) {
return intermediateChats.remove(player);
}
public ProcessedChat getProcessedChat(Player player) {
public ProcessedChat getProcessedChat(final Player player) {
return processedChats.getIfPresent(player);
}
public void setProcessedChat(Player player, ProcessedChat chat) {
public void setProcessedChat(final Player player, final ProcessedChat chat) {
processedChats.put(player, chat);
}
public ProcessedChat clearProcessedChat(final Player player) {
final ProcessedChat chat = processedChats.getIfPresent(player);
processedChats.invalidate(player);
return chat;
}
public Chat getIntermediateOrElseProcessedChat(final Player player) {
final IntermediateChat chat = getIntermediateChat(player);
if (chat != null) {
return chat;
}
return getProcessedChat(player);
}
public static abstract class Chat {
private final User user;
private final String type;
@ -51,11 +65,11 @@ public class ChatProcessingCache {
this.originalMessage = originalMessage;
}
User getUser() {
public User getUser() {
return user;
}
String getType() {
public String getType() {
return type;
}
@ -63,32 +77,39 @@ public class ChatProcessingCache {
return originalMessage;
}
final String getLongType() {
public final String getLongType() {
return type.length() == 0 ? "chat" : "chat-" + type;
}
}
public static class ProcessedChat extends Chat {
private final String message;
private final String format;
private final Trade charge;
public ProcessedChat(final IEssentials ess, final IntermediateChat sourceChat) {
super(sourceChat.getUser(), sourceChat.getType(), sourceChat.getOriginalMessage());
this.message = sourceChat.messageResult;
this.format = sourceChat.formatResult;
this.charge = new Trade(getLongType(), ess);
this.message = sourceChat.modifiedMessage;
}
public String getMessage() {
return message;
}
public String getFormat() {
return format;
}
public Trade getCharge() {
return charge;
}
}
public static class IntermediateChat extends Chat {
private String modifiedMessage;
private String messageResult;
private String formatResult;
private long radius;
public IntermediateChat(final User user, final String type, final String originalMessage) {
@ -100,15 +121,24 @@ public class ChatProcessingCache {
}
void setRadius(final long radius) {
// TODO: use or remove
this.radius = radius;
}
public String getModifiedMessage() {
return modifiedMessage;
public String getMessageResult() {
return messageResult;
}
public void setModifiedMessage(String modifiedMessage) {
this.modifiedMessage = modifiedMessage;
public void setMessageResult(String messageResult) {
this.messageResult = messageResult;
}
public String getFormatResult() {
return formatResult;
}
public void setFormatResult(String formatResult) {
this.formatResult = formatResult;
}
}

View File

@ -1,5 +1,46 @@
package com.earth2me.essentials.chat.processing;
public class LegacyChatHandler {
// TODO
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.chat.EssentialsChat;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.plugin.PluginManager;
public class LegacyChatHandler extends AbstractChatHandler {
public LegacyChatHandler(Essentials ess, EssentialsChat essChat) {
super(ess, essChat);
}
public void registerListeners() {
final PluginManager pm = essChat.getServer().getPluginManager();
pm.registerEvents(new ChatLowest(), essChat);
pm.registerEvents(new ChatNormal(), essChat);
pm.registerEvents(new ChatHighest(), essChat);
}
private class ChatLowest implements ChatListener {
@Override
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatFormat(event);
}
}
private class ChatNormal implements ChatListener {
@Override
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatRecipients(event);
}
}
private class ChatHighest implements ChatListener {
@Override
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatPostFormat(event);
handleChatSubmit(event);
}
}
}

View File

@ -1,6 +1,7 @@
package com.earth2me.essentials.chat.processing;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.I18n;
import com.earth2me.essentials.chat.EssentialsChat;
import com.earth2me.essentials.utils.VersionUtil;
import org.bukkit.event.EventHandler;
@ -16,35 +17,104 @@ public class SignedChatHandler extends AbstractChatHandler {
super(ess, essChat);
}
boolean tryRegisterListeners() {
public boolean tryRegisterListeners() {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_19_1_R01)) {
return false;
}
try {
final Class<?> previewClass = Class.forName("org.bukkit.event.player.AsyncPlayerChatPreviewEvent");
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_19_1_R01) || !AsyncPlayerChatEvent.class.isAssignableFrom(previewClass)) {
if (!AsyncPlayerChatEvent.class.isAssignableFrom(previewClass)) {
essChat.getLogger().severe(I18n.tl("essChatNoSecureMsg", essChat.getDescription().getVersion()));
return false;
}
} catch (ClassNotFoundException e) {
essChat.getLogger().severe(I18n.tl("essChatNoSecureMsg", essChat.getDescription().getVersion()));
return false;
}
final PluginManager pm = essChat.getServer().getPluginManager();
pm.registerEvents(new Lowest(), essChat);
// TODO Normal
// TODO Highest (or Monitor?)
pm.registerEvents(new PreviewLowest(), essChat);
pm.registerEvents(new PreviewHighest(), essChat);
pm.registerEvents(new ChatLowest(), essChat);
pm.registerEvents(new ChatNormal(), essChat);
pm.registerEvents(new ChatHighest(), essChat);
return true;
}
private void handleChatApplyPreview(AsyncPlayerChatEvent event) {
final ChatProcessingCache.ProcessedChat chat = cache.getProcessedChat(event.getPlayer());
if (chat == null) {
handleChatFormat(event);
handleChatPostFormat(event);
} else {
event.setFormat(chat.getFormat());
event.setMessage(chat.getMessage());
}
}
private void handleChatConfirmPreview(AsyncPlayerChatEvent event) {
if (!ess.getSettings().isDebug()) return;
final ChatProcessingCache.ProcessedChat chat = cache.getProcessedChat(event.getPlayer());
if (chat == null) {
// Can't confirm preview for some reason
essChat.getLogger().info("Processed chat missing for " + event.getPlayer());
} else {
if (!event.getFormat().equals(chat.getFormat())) {
// Chat format modified by another plugin
essChat.getLogger().info("Chat format has been modified for " + event.getPlayer());
essChat.getLogger().info("Expected '" + chat.getFormat() + "', got '" + event.getFormat());
}
if (!event.getMessage().equals(chat.getMessage())) {
// Chat message modified by another plugin
essChat.getLogger().info("Chat message has been modified for " + event.getPlayer());
essChat.getLogger().info("Expected '" + chat.getMessage() + "', got '" + event.getMessage());
}
}
}
private interface PreviewListener extends Listener {
void onPlayerChatPreview(AsyncPlayerChatPreviewEvent event);
}
private class Lowest implements PreviewListener {
private class PreviewLowest implements PreviewListener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerChatPreview(AsyncPlayerChatPreviewEvent event) {
// TODO
handleChatFormat(event);
}
}
// TODO preview on Normal, Highest
// TODO chat on ???? priority, how do we do this without exploding all over other plugins?
private class PreviewHighest implements PreviewListener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerChatPreview(AsyncPlayerChatPreviewEvent event) {
handleChatPostFormat(event);
}
}
private class ChatLowest implements ChatListener {
@Override
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatApplyPreview(event);
}
}
private class ChatNormal implements ChatListener {
@Override
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatRecipients(event);
}
}
private class ChatHighest implements ChatListener {
@Override
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerChat(AsyncPlayerChatEvent event) {
handleChatConfirmPreview(event);
handleChatSubmit(event);
}
}
}