From 447b9db3978ee536401498848cdc9a69a3ac1be5 Mon Sep 17 00:00:00 2001 From: Ali Moghnieh Date: Tue, 27 Oct 2015 17:34:59 +0000 Subject: [PATCH] Rewrote messaging structure for more abstractness. This commit adds a new boolean-configurable feature called last-message-reply-recipient, defaults to true for new installs and false for old installs, which states whether to use the new messaging functionality or not. This commit deprecates Console#getCommandSender(Server) and provides Console#getInstance()#getCommandSender() for future usability. --- .../earth2me/essentials/CommandSource.java | 13 +- .../src/com/earth2me/essentials/Console.java | 67 +++++++-- .../com/earth2me/essentials/Essentials.java | 5 + .../src/com/earth2me/essentials/IReplyTo.java | 17 --- .../com/earth2me/essentials/ISettings.java | 2 + .../src/com/earth2me/essentials/Settings.java | 4 + .../src/com/earth2me/essentials/User.java | 33 +++-- .../essentials/commands/Commandmsg.java | 52 ++----- .../essentials/commands/Commandr.java | 38 ++---- .../messaging/IMessageRecipient.java | 96 +++++++++++++ .../messaging/SimpleMessageRecipient.java | 129 ++++++++++++++++++ Essentials/src/config.yml | 4 + .../earth2me/essentials/MessagingTest.java | 104 ++++++++++++++ .../earth2me/essentials/xmpp/XMPPManager.java | 2 +- 14 files changed, 444 insertions(+), 122 deletions(-) delete mode 100644 Essentials/src/com/earth2me/essentials/IReplyTo.java create mode 100644 Essentials/src/com/earth2me/essentials/messaging/IMessageRecipient.java create mode 100644 Essentials/src/com/earth2me/essentials/messaging/SimpleMessageRecipient.java create mode 100644 Essentials/test/com/earth2me/essentials/MessagingTest.java diff --git a/Essentials/src/com/earth2me/essentials/CommandSource.java b/Essentials/src/com/earth2me/essentials/CommandSource.java index bb9049553..8d0305024 100644 --- a/Essentials/src/com/earth2me/essentials/CommandSource.java +++ b/Essentials/src/com/earth2me/essentials/CommandSource.java @@ -4,8 +4,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -public class CommandSource implements IReplyTo { - private CommandSource replyTo = null; +public class CommandSource { protected CommandSender sender; public CommandSource(final CommandSender base) { @@ -37,14 +36,4 @@ public class CommandSource implements IReplyTo { sender.sendMessage(message); } } - - @Override - public void setReplyTo(final CommandSource user) { - replyTo = user; - } - - @Override - public CommandSource getReplyTo() { - return replyTo; - } } diff --git a/Essentials/src/com/earth2me/essentials/Console.java b/Essentials/src/com/earth2me/essentials/Console.java index 7e560ba81..23db84039 100644 --- a/Essentials/src/com/earth2me/essentials/Console.java +++ b/Essentials/src/com/earth2me/essentials/Console.java @@ -1,32 +1,73 @@ package com.earth2me.essentials; +import com.earth2me.essentials.messaging.IMessageRecipient; +import com.earth2me.essentials.messaging.SimpleMessageRecipient; + import org.bukkit.Server; import org.bukkit.command.CommandSender; -public final class Console implements IReplyTo { - private static final Console instance = new Console(); - private CommandSource replyTo; - public final static String NAME = "Console"; +public final class Console implements IMessageRecipient { + public static final String NAME = "Console"; + private static Console instance; // Set in essentials + + private final IEssentials ess; + private final IMessageRecipient messageRecipient; - private Console() { + public static Console getInstance() { + return instance; } + static void setInstance(IEssentials ess) { // Called in Essentials#onEnable() + instance = new Console(ess); + } + + /** + * @deprecated Use {@link Console#getCommandSender()} + */ + @Deprecated public static CommandSender getCommandSender(Server server) throws Exception { return server.getConsoleSender(); } - @Override - public void setReplyTo(CommandSource user) { - replyTo = user; + private Console(IEssentials ess) { + this.ess = ess; + this.messageRecipient = new SimpleMessageRecipient(ess, this); } - @Override - public CommandSource getReplyTo() { - return replyTo; + public CommandSender getCommandSender() { + return ess.getServer().getConsoleSender(); } - public static Console getConsoleReplyTo() { - return instance; + @Override public String getName() { + return Console.NAME; + } + + @Override public String getDisplayName() { + return Console.NAME; + } + + @Override public void sendMessage(String message) { + getCommandSender().sendMessage(message); + } + + /* ================================ + * >> DELEGATE METHODS + * ================================ */ + + @Override public MessageResponse sendMessage(IMessageRecipient recipient, String message) { + return this.messageRecipient.sendMessage(recipient, message); + } + + @Override public MessageResponse onReceiveMessage(IMessageRecipient sender, String message) { + return this.messageRecipient.onReceiveMessage(sender, message); + } + + @Override public IMessageRecipient getReplyRecipient() { + return this.messageRecipient.getReplyRecipient(); + } + + @Override public void setReplyRecipient(IMessageRecipient recipient) { + this.messageRecipient.setReplyRecipient(recipient); } } diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java index da8c979a7..e7c27109c 100644 --- a/Essentials/src/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/com/earth2me/essentials/Essentials.java @@ -119,6 +119,8 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { i18n = new I18n(this); i18n.onEnable(); i18n.updateLocale("en"); + Console.setInstance(this); + LOGGER.log(Level.INFO, tl("usingTempFolderForTesting")); LOGGER.log(Level.INFO, dataFolder.toString()); this.initialize(null, server, new PluginDescriptionFile(new FileReader(new File("src" + File.separator + "plugin.yml"))), dataFolder, null, null); @@ -140,6 +142,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { i18n = new I18n(this); i18n.onEnable(); execTimer.mark("I18n1"); + + Console.setInstance(this); + String serverString = Bukkit.getServer().getClass().getName(); for (int i = 1; i <= 7; i++) { if (serverString.contains(".v1_" + i + "_R")) { diff --git a/Essentials/src/com/earth2me/essentials/IReplyTo.java b/Essentials/src/com/earth2me/essentials/IReplyTo.java deleted file mode 100644 index a02a458a9..000000000 --- a/Essentials/src/com/earth2me/essentials/IReplyTo.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.earth2me.essentials; - -public interface IReplyTo { - /** - * Sets the user to reply to - * - * @param user - */ - void setReplyTo(CommandSource user); - - /** - * Gets the user the sender should reply to - * - * @return - */ - CommandSource getReplyTo(); -} diff --git a/Essentials/src/com/earth2me/essentials/ISettings.java b/Essentials/src/com/earth2me/essentials/ISettings.java index 7d1e384dc..5c2f0e36c 100644 --- a/Essentials/src/com/earth2me/essentials/ISettings.java +++ b/Essentials/src/com/earth2me/essentials/ISettings.java @@ -225,4 +225,6 @@ public interface ISettings extends IConf { boolean isNotifyNoNewMail(); boolean isDropItemsIfFull(); + + boolean isLastMessageReplyRecipient(); } diff --git a/Essentials/src/com/earth2me/essentials/Settings.java b/Essentials/src/com/earth2me/essentials/Settings.java index 6b41f7031..9099297ca 100644 --- a/Essentials/src/com/earth2me/essentials/Settings.java +++ b/Essentials/src/com/earth2me/essentials/Settings.java @@ -1112,4 +1112,8 @@ public class Settings implements net.ess3.api.ISettings { long count = Runtime.getRuntime().maxMemory() / 1024 / 96; return config.getInt("max-user-cache-count", (int) count); } + + @Override public boolean isLastMessageReplyRecipient() { + return config.getBoolean("last-message-reply-recipient", false); + } } diff --git a/Essentials/src/com/earth2me/essentials/User.java b/Essentials/src/com/earth2me/essentials/User.java index 3ba092de3..825650ce4 100644 --- a/Essentials/src/com/earth2me/essentials/User.java +++ b/Essentials/src/com/earth2me/essentials/User.java @@ -1,6 +1,8 @@ package com.earth2me.essentials; import com.earth2me.essentials.commands.IEssentialsCommand; +import com.earth2me.essentials.messaging.IMessageRecipient; +import com.earth2me.essentials.messaging.SimpleMessageRecipient; import com.earth2me.essentials.register.payment.Method; import com.earth2me.essentials.register.payment.Methods; import com.earth2me.essentials.utils.DateUtil; @@ -27,9 +29,9 @@ import java.util.logging.Logger; import static com.earth2me.essentials.I18n.tl; -public class User extends UserData implements Comparable, IReplyTo, net.ess3.api.IUser { +public class User extends UserData implements Comparable, IMessageRecipient, net.ess3.api.IUser { private static final Logger logger = Logger.getLogger("Essentials"); - private CommandSource replyTo = null; + private IMessageRecipient messageRecipient; private transient UUID teleportRequester; private transient boolean teleportRequestHere; private transient Location teleportLocation; @@ -57,6 +59,7 @@ public class User extends UserData implements Comparable, IReplyTo, net.es if (this.getBase().isOnline()) { lastOnlineActivity = System.currentTimeMillis(); } + this.messageRecipient = new SimpleMessageRecipient(ess, this); } User update(final Player base) { @@ -680,16 +683,6 @@ public class User extends UserData implements Comparable, IReplyTo, net.es } } - @Override - public void setReplyTo(final CommandSource user) { - replyTo = user; - } - - @Override - public CommandSource getReplyTo() { - return replyTo; - } - @Override public int compareTo(final User other) { return FormatUtil.stripFormat(getDisplayName()).compareToIgnoreCase(FormatUtil.stripFormat(other.getDisplayName())); @@ -718,4 +711,20 @@ public class User extends UserData implements Comparable, IReplyTo, net.es public String getName() { return this.getBase().getName(); } + + @Override public MessageResponse sendMessage(IMessageRecipient recipient, String message) { + return this.messageRecipient.sendMessage(recipient, message); + } + + @Override public MessageResponse onReceiveMessage(IMessageRecipient sender, String message) { + return this.messageRecipient.onReceiveMessage(sender, message); + } + + @Override public IMessageRecipient getReplyRecipient() { + return this.messageRecipient.getReplyRecipient(); + } + + @Override public void setReplyRecipient(IMessageRecipient recipient) { + this.messageRecipient.setReplyRecipient(recipient); + } } diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandmsg.java b/Essentials/src/com/earth2me/essentials/commands/Commandmsg.java index 83524d7d7..c2f0c5b03 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandmsg.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandmsg.java @@ -1,18 +1,17 @@ package com.earth2me.essentials.commands; -import com.earth2me.essentials.CommandSource; -import com.earth2me.essentials.Console; -import com.earth2me.essentials.IReplyTo; -import com.earth2me.essentials.User; -import com.earth2me.essentials.utils.FormatUtil; -import org.bukkit.Server; -import org.bukkit.command.CommandSender; - import static com.earth2me.essentials.I18n.tl; +import com.earth2me.essentials.CommandSource; +import com.earth2me.essentials.Console; +import com.earth2me.essentials.User; +import com.earth2me.essentials.messaging.IMessageRecipient; +import com.earth2me.essentials.utils.FormatUtil; + +import org.bukkit.Server; + public class Commandmsg extends EssentialsLoopCommand { - final String translatedMe = tl("me"); public Commandmsg() { super("msg"); @@ -38,15 +37,10 @@ public class Commandmsg extends EssentialsLoopCommand { canWildcard = true; } + // Sending messages to console if (args[0].equalsIgnoreCase(Console.NAME)) { - final IReplyTo replyTo = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : Console.getConsoleReplyTo(); - final String senderName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.NAME; - - sender.sendMessage(tl("msgFormat", translatedMe, Console.NAME, message)); - CommandSender cs = Console.getCommandSender(server); - cs.sendMessage(tl("msgFormat", senderName, translatedMe, message)); - replyTo.setReplyTo(new CommandSource(cs)); - Console.getConsoleReplyTo().setReplyTo(sender); + IMessageRecipient messageSender = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : Console.getInstance(); + messageSender.sendMessage(Console.getInstance(), message); return; } @@ -54,26 +48,8 @@ public class Commandmsg extends EssentialsLoopCommand { } @Override - protected void updatePlayer(final Server server, final CommandSource sender, final User matchedUser, final String[] args) { - final IReplyTo replyTo = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : Console.getConsoleReplyTo(); - final String senderName = sender.isPlayer() ? sender.getPlayer().getDisplayName() : Console.NAME; - - if (matchedUser.isAfk()) { - sender.sendMessage(tl("userAFK", matchedUser.getDisplayName())); - } - - sender.sendMessage(tl("msgFormat", translatedMe, matchedUser.getDisplayName(), args[0])); - if (sender.isPlayer() && matchedUser.isIgnoredPlayer(ess.getUser(sender.getPlayer()))) { - return; - } - - if (matchedUser.isIgnoreMsg()) { - sender.sendMessage(tl("msgIgnore", matchedUser.getDisplayName())); - return; - } - - matchedUser.sendMessage(tl("msgFormat", senderName, translatedMe, args[0])); - replyTo.setReplyTo(matchedUser.getSource()); - matchedUser.setReplyTo(sender); + protected void updatePlayer(final Server server, final CommandSource sender, final User messageReceiver, final String[] args) { + IMessageRecipient messageSender = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : Console.getInstance(); + messageSender.sendMessage(messageReceiver, args[0]); // args[0] is the message. } } diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandr.java b/Essentials/src/com/earth2me/essentials/commands/Commandr.java index 2f2dd1318..f82f1c635 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandr.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandr.java @@ -2,8 +2,8 @@ package com.earth2me.essentials.commands; import com.earth2me.essentials.CommandSource; import com.earth2me.essentials.Console; -import com.earth2me.essentials.IReplyTo; import com.earth2me.essentials.User; +import com.earth2me.essentials.messaging.IMessageRecipient; import com.earth2me.essentials.utils.FormatUtil; import org.bukkit.Server; @@ -22,43 +22,23 @@ public class Commandr extends EssentialsCommand { } String message = getFinalArg(args, 0); - IReplyTo replyTo; - String senderName; + IMessageRecipient messageSender; if (sender.isPlayer()) { User user = ess.getUser(sender.getPlayer()); message = FormatUtil.formatMessage(user, "essentials.msg", message); - replyTo = user; - senderName = user.getDisplayName(); + messageSender = user; } else { message = FormatUtil.replaceFormat(message); - replyTo = Console.getConsoleReplyTo(); - senderName = Console.NAME; + messageSender = Console.getInstance(); } - final CommandSource target = replyTo.getReplyTo(); - - if (target == null || (target.isPlayer() && !target.getPlayer().isOnline())) { + final IMessageRecipient target = messageSender.getReplyRecipient(); + + // Check to make sure the sender does have a quick-reply recipient, and that the recipient is online. + if (target == null || (target instanceof User && !((User) target).getBase().isOnline())) { throw new Exception(tl("foreverAlone")); } - - final String targetName = target.isPlayer() ? target.getPlayer().getDisplayName() : Console.NAME; - - sender.sendMessage(tl("msgFormat", tl("me"), targetName, message)); - if (target.isPlayer()) { - User player = ess.getUser(target.getPlayer()); - if (sender.isPlayer() && player.isIgnoredPlayer(ess.getUser(sender.getPlayer()))) { - return; - } - } - target.sendMessage(tl("msgFormat", senderName, tl("me"), message)); - replyTo.setReplyTo(target); - if (target != sender) { - if (target.isPlayer()) { - ess.getUser(target.getPlayer()).setReplyTo(sender); - } else { - Console.getConsoleReplyTo().setReplyTo(sender); - } - } + messageSender.sendMessage(target, message); } } diff --git a/Essentials/src/com/earth2me/essentials/messaging/IMessageRecipient.java b/Essentials/src/com/earth2me/essentials/messaging/IMessageRecipient.java new file mode 100644 index 000000000..bf2d9c8b9 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/messaging/IMessageRecipient.java @@ -0,0 +1,96 @@ +package com.earth2me.essentials.messaging; + +/** + * Represents an interface for message recipients. + */ +public interface IMessageRecipient { + + /** + * Sends (prints) a message to this recipient. + * + * @param message message + */ + void sendMessage(String message); + + /** + * This method is called when this {@link IMessageRecipient} is sending a message to another {@link IMessageRecipient}. + *
+ * The {@link MessageResponse} that is returned is used to determine what exactly should happen in the {@link #sendMessage(IMessageRecipient, + * String)} implementation by the {@code sender}. + * + * @param recipient recipient to receive the {@code message} + * @param message message to send + * + * @return the response of the message + */ + MessageResponse sendMessage(IMessageRecipient recipient, String message); + + /** + * This method is called when this recipient is receiving a message from another {@link IMessageRecipient}. + *
+ * The {@link MessageResponse} that is returned is used to determine what exactly should happen in the {@link #sendMessage(IMessageRecipient, + * String)} implementation by the {@code sender}. + *

+ * This method should only be called by {@link #sendMessage(IMessageRecipient, String)}. + * + * @param sender sender of the {@code message} + * @param message message being received + * + * @return the response of the message + */ + MessageResponse onReceiveMessage(IMessageRecipient sender, String message); + + /** + * Returns the name of this recipient. This name is typically used internally to identify this recipient. + * + * @return name of this recipient + * + * @see #getDisplayName() + */ + String getName(); + + /** + * Returns the display name of this recipient. This name is typically used when formatting messages. + * + * @return display name of this recipient + */ + String getDisplayName(); + + /** + * Returns the {@link IMessageRecipient} this recipient should send replies to. + * + * @return message recipient + */ + IMessageRecipient getReplyRecipient(); + + /** + * Sets the {@link IMessageRecipient} this recipient should send replies to. + * + * @param recipient message recipient to set + */ + void setReplyRecipient(IMessageRecipient recipient); + + /** + * Represents a response for sending or receiving a message when using {@link IMessageRecipient#sendMessage(IMessageRecipient, String)} or + * {@link IMessageRecipient#onReceiveMessage(IMessageRecipient, String)}. + */ + enum MessageResponse { + /** States that the message was received and assumed readable by the receiver. */ + SUCCESS, + /** States that the message was received, but the receiver was away, assuming the message was not read. */ + SUCCESS_BUT_AFK, + /** States that the message was NOT received as a result of the receiver ignoring all messages. */ + MESSAGES_IGNORED, + /** States that the message was NOT received as a result of the sender being ignored by the recipient. */ + SENDER_IGNORED; + + /** + * Returns whether this response is a success. In other words equal to {@link #SUCCESS} or {@link #SUCCESS_BUT_AFK} + * + * @return whether the response is a success + */ + public boolean isSuccess() { + return this == SUCCESS || this == SUCCESS_BUT_AFK; + } + } +} diff --git a/Essentials/src/com/earth2me/essentials/messaging/SimpleMessageRecipient.java b/Essentials/src/com/earth2me/essentials/messaging/SimpleMessageRecipient.java new file mode 100644 index 000000000..e83c8e645 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/messaging/SimpleMessageRecipient.java @@ -0,0 +1,129 @@ +package com.earth2me.essentials.messaging; + +import static com.earth2me.essentials.I18n.tl; + +import com.earth2me.essentials.Console; +import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.IUser; +import com.earth2me.essentials.User; + +import java.lang.ref.WeakReference; + +/** + * Represents a simple reusable implementation of {@link IMessageRecipient}. This class provides functionality for the following methods: + *

    + *
  • {@link IMessageRecipient#sendMessage(IMessageRecipient, String)}
  • + *
  • {@link IMessageRecipient#onReceiveMessage(IMessageRecipient, String)}
  • + *
  • {@link IMessageRecipient#getReplyRecipient()}
  • + *
  • {@link IMessageRecipient#setReplyRecipient(IMessageRecipient)}
  • + *
+ * + * The given {@code parent} must implement the following methods to prevent overflow: + *
    + *
  • {@link IMessageRecipient#sendMessage(String)}
  • + *
  • {@link IMessageRecipient#getName()}
  • + *
  • {@link IMessageRecipient#getDisplayName()}
  • + *
+ * + * The reply-recipient is wrapped in a {@link WeakReference}. + */ +public class SimpleMessageRecipient implements IMessageRecipient { + + private final IEssentials ess; + private final IMessageRecipient parent; + + private WeakReference replyRecipient; + + public SimpleMessageRecipient(IEssentials ess, IMessageRecipient parent) { + this.ess = ess; + this.parent = parent; + } + + @Override + public void sendMessage(String message) { + this.parent.sendMessage(message); + } + + @Override + public String getName() { + return this.parent.getName(); + } + + @Override public String getDisplayName() { + return this.parent.getDisplayName(); + } + + @Override public MessageResponse sendMessage(IMessageRecipient recipient, String message) { + MessageResponse messageResponse = recipient.onReceiveMessage(this.parent, message); + switch (messageResponse) { + case MESSAGES_IGNORED: + sendMessage(tl("msgIgnore", getDisplayName())); + break; + case SENDER_IGNORED: + break; + // When this recipient is AFK, notify the sender. Then, proceed to send the message. + case SUCCESS_BUT_AFK: // TODO double check this functionality! + sendMessage(tl("userAFK", getDisplayName())); + default: + sendMessage(tl("msgFormat", tl("me"), recipient.getDisplayName(), message)); + } + + if (ess.getSettings().isLastMessageReplyRecipient()) { + // If the message was a success, set this sender's reply-recipient to the current recipient. + if (messageResponse.isSuccess()) { + setReplyRecipient(recipient); + } + } + return messageResponse; + } + + @Override + public MessageResponse onReceiveMessage(IMessageRecipient sender, String message) { + User user = this.parent instanceof User ? (User) this.parent : null; + boolean afk = false; + if (user != null) { + if (user.isIgnoreMsg() + && !(sender instanceof Console)) { // Console must never be ignored. + return MessageResponse.MESSAGES_IGNORED; + } + afk = user.isAfk(); + // Check whether this recipient ignores the sender, only if the sender is not the console. + if (sender instanceof IUser && user.isIgnoredPlayer((IUser) sender)) { + return MessageResponse.SENDER_IGNORED; + } + } + // Display the formatted message to this recipient. + sendMessage(tl("msgFormat", sender.getDisplayName(), tl("me"), message)); + + if (ess.getSettings().isLastMessageReplyRecipient()) { + // If this recipient doesn't have a reply recipient, initiate by setting the first + // message sender to this recipient's replyRecipient. + if (getReplyRecipient() == null) { + setReplyRecipient(sender); + } + } else { // Old message functionality, always set the reply recipient to the last person who sent us a message. + setReplyRecipient(sender); + } + return afk ? MessageResponse.SUCCESS_BUT_AFK : MessageResponse.SUCCESS; + } + + /** + * {@inheritDoc} + *

+ * This {@link com.earth2me.essentials.messaging.SimpleMessageRecipient} implementation stores the a weak reference to the recipient. + */ + @Override + public IMessageRecipient getReplyRecipient() { + return replyRecipient == null ? null : replyRecipient.get(); + } + + /** + * {@inheritDoc} + *

+ * This {@link com.earth2me.essentials.messaging.SimpleMessageRecipient} implementation stores the a weak reference to the recipient. + */ + @Override + public void setReplyRecipient(final IMessageRecipient replyRecipient) { + this.replyRecipient = new WeakReference<>(replyRecipient); + } +} diff --git a/Essentials/src/config.yml b/Essentials/src/config.yml index 15a166fbe..b2419c1f9 100644 --- a/Essentials/src/config.yml +++ b/Essentials/src/config.yml @@ -452,6 +452,10 @@ mails-per-minute: 1000 # Set to -1 to disable, and essentials.tempban.unlimited can be used to override. max-tempban-time: -1 +# Changes /reply functionality. If true, /r goes to the person you messaged last, otherwise the first person that messaged you. +# If false, /r goes to the last person that messaged you. +last-message-reply-recipient: true + ############################################################ # +------------------------------------------------------+ # # | EssentialsHome | # diff --git a/Essentials/test/com/earth2me/essentials/MessagingTest.java b/Essentials/test/com/earth2me/essentials/MessagingTest.java new file mode 100644 index 000000000..10580161d --- /dev/null +++ b/Essentials/test/com/earth2me/essentials/MessagingTest.java @@ -0,0 +1,104 @@ +package com.earth2me.essentials; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import com.earth2me.essentials.commands.IEssentialsCommand; +import com.earth2me.essentials.commands.NoChargeException; + +import org.bukkit.World.Environment; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.InvalidDescriptionException; +import org.junit.Test; + +import java.io.IOException; + + +public class MessagingTest { + + private final OfflinePlayer base1; + private final Essentials ess; + private final FakeServer server; + + public MessagingTest() { + server = new FakeServer(); + server.createWorld("testWorld", Environment.NORMAL); + ess = new Essentials(server); + try { + ess.setupForTesting(server); + } catch (InvalidDescriptionException ex) { + fail("InvalidDescriptionException"); + } catch (IOException ex) { + fail("IOException"); + } + base1 = server.createPlayer("testPlayer1"); + server.addPlayer(base1); + ess.getUser(base1); + } + + private void runCommand(String command, User user, String args) throws Exception { + runCommand(command, user, args.split("\\s+")); + } + + private void runCommand(String command, User user, String[] args) throws Exception { + IEssentialsCommand cmd; + + try { + cmd = (IEssentialsCommand) Essentials.class.getClassLoader() + .loadClass("com.earth2me.essentials.commands.Command" + command).newInstance(); + cmd.setEssentials(ess); + cmd.run(server, user, command, null, args); + } catch (NoChargeException ex) { + } + + } + + private void runConsoleCommand(String command, String args) throws Exception { + runConsoleCommand(command, args.split("\\s+")); + } + + private void runConsoleCommand(String command, String[] args) throws Exception { + IEssentialsCommand cmd; + + CommandSender sender = server.getConsoleSender(); + + try { + cmd = (IEssentialsCommand) Essentials.class.getClassLoader() + .loadClass("com.earth2me.essentials.commands.Command" + command).newInstance(); + cmd.setEssentials(ess); + cmd.run(server, new CommandSource(sender), command, null, args); + } catch (NoChargeException ex) { + } + } + + @Test(expected = Exception.class) // I really don't like this, but see note below about console reply + public void testMessage() throws Exception { + User user1 = ess.getUser(base1); + Console console = Console.getInstance(); + + if (ess.getSettings().isLastMessageReplyRecipient()) { + assertNull(console.getReplyRecipient()); // console never messaged or received messages from anyone. + + // user1 messages console saying "Hey, master!" + runCommand("msg", user1, console.getName() + " Hey, master!"); + + // console should now have its reply-recipient as user1, since the console doesn't have a previous recipient. + assertEquals(console.getReplyRecipient(), user1); + + if (ess.getSettings().isLastMessageReplyRecipient()) { + runCommand("r", user1, "This is me sending you a message using /r without you replying!"); + } + + // Not really much of a strict test, but just "testing" console output. + user1._setAfk(true); + + // Console replies using "/r Hey, son!" + // + // This throws Exception because the base1 is an OfflinePlayer (isOnline() returns false). + runConsoleCommand("r", "Hey, son!"); + } else { + assertNull(console.getReplyRecipient()); // user2 never received messages from anyone. + } + } +} diff --git a/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java b/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java index 90173b5ad..95f987280 100644 --- a/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java +++ b/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java @@ -304,7 +304,7 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager private void sendCommand(final Chat chat, final String message) { if (config.getStringList("op-users").contains(StringUtils.parseBareAddress(chat.getParticipant()))) { try { - parent.getServer().dispatchCommand(Console.getCommandSender(parent.getServer()), message.substring(1)); + parent.getServer().dispatchCommand(Console.getInstance().getCommandSender(), message.substring(1)); } catch (Exception ex) { LOGGER.log(Level.SEVERE, ex.getMessage(), ex); }