From 8cbd9b79355a1f648b18155774e9b7c2e73b382f Mon Sep 17 00:00:00 2001 From: Josh Roy <10731363+JRoy@users.noreply.github.com> Date: Fri, 19 Feb 2021 10:13:49 -0500 Subject: [PATCH] Add /editsign copy + paste (#3989) Adds `copy` and `paste` subcommands to `/editsign` to allow users to copy and paste the contents of signs without having to use the tab-completion output of `/editsign set`. The `/editsign copy` command will also perform format-permission checks to ensure the user copying the sign has the proper permission to use said formatting. Closes #3973. --- .../java/com/earth2me/essentials/User.java | 6 ++++ .../essentials/commands/Commandeditsign.java | 33 +++++++++++++++++-- .../src/main/resources/messages.properties | 6 +++- Essentials/src/main/resources/plugin.yml | 2 +- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Essentials/src/main/java/com/earth2me/essentials/User.java b/Essentials/src/main/java/com/earth2me/essentials/User.java index 25b7a9fd9..6b9f78cb7 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/User.java +++ b/Essentials/src/main/java/com/earth2me/essentials/User.java @@ -10,6 +10,7 @@ import com.earth2me.essentials.utils.EnumUtil; import com.earth2me.essentials.utils.FormatUtil; import com.earth2me.essentials.utils.NumberUtil; import com.earth2me.essentials.utils.VersionUtil; +import com.google.common.collect.Lists; import net.ess3.api.IEssentials; import net.ess3.api.MaxMoneyException; import net.ess3.api.events.AfkStatusChangeEvent; @@ -71,6 +72,7 @@ public class User extends UserData implements Comparable, IMessageRecipien private long lastNotifiedAboutMailsMs; private String lastHomeConfirmation; private long lastHomeConfirmationTimestamp; + private transient final List signCopy = Lists.newArrayList("", "", "", ""); public User(final Player base, final IEssentials ess) { super(base, ess); @@ -1045,6 +1047,10 @@ public class User extends UserData implements Comparable, IMessageRecipien this.lastHomeConfirmationTimestamp = System.currentTimeMillis(); } + public List getSignCopy() { + return signCopy; + } + public boolean isBaltopExempt() { if (getBase().isOnline()) { final boolean exempt = isAuthorized("essentials.balancetop.exclude"); diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandeditsign.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandeditsign.java index b540dadd5..2001c35c2 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandeditsign.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandeditsign.java @@ -53,18 +53,47 @@ public class Commandeditsign extends EssentialsCommand { sign.update(); user.sendMessage(tl("editsignCommandClearLine", line + 1)); } + } else if (args[0].equalsIgnoreCase("copy") || args[0].equalsIgnoreCase("paste")) { + final boolean copy = args[0].equalsIgnoreCase("copy"); + final String tlPrefix = copy ? "editsignCopy" : "editsignPaste"; + final int line = args.length == 1 ? -1 : Integer.parseInt(args[1]) - 1; + + if (line == -1) { + for (int i = 0; i < 4; i++) { + processSignCopyPaste(user, sign, i, copy); + } + user.sendMessage(tl(tlPrefix, commandLabel)); + } else { + processSignCopyPaste(user, sign, line, copy); + user.sendMessage(tl(tlPrefix + "Line", line + 1, commandLabel)); + } + + if (!copy) { + sign.update(); + } } else { throw new NotEnoughArgumentsException(); } } catch (final IndexOutOfBoundsException e) { - throw new Exception(tl("editsignCommandNoLine")); + throw new Exception(tl("editsignCommandNoLine"), e); } } + private void processSignCopyPaste(final User user, final Sign sign, final int index, final boolean copy) { + if (copy) { + // We use unformat here to prevent players from copying signs with colors that they do not have permission to use. + user.getSignCopy().set(index, FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(index))); + return; + } + + final String line = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(index)); + sign.setLine(index, line == null ? "" : line); + } + @Override protected List getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) { if (args.length == 1) { - return Lists.newArrayList("set", "clear"); + return Lists.newArrayList("set", "clear", "copy", "paste"); } else if (args.length == 2) { return Lists.newArrayList("1", "2", "3", "4"); } else if (args.length == 3 && args[0].equalsIgnoreCase("set") && NumberUtil.isPositiveInt(args[1])) { diff --git a/Essentials/src/main/resources/messages.properties b/Essentials/src/main/resources/messages.properties index b475907e9..9b8b76f61 100644 --- a/Essentials/src/main/resources/messages.properties +++ b/Essentials/src/main/resources/messages.properties @@ -742,7 +742,11 @@ editsignCommandLimit=\u00a74Your provided text is too big to fit on the target s editsignCommandNoLine=\u00a74You must enter a line number between \u00a7c1-4\u00a74. editsignCommandSetSuccess=\u00a76Set line\u00a7c {0}\u00a76 to "\u00a7c{1}\u00a76". editsignCommandTarget=\u00a74You must be looking at a sign to edit its text. -editsignCommandUsage=/ [line number] [text] +editsignCopy=\u00a76Sign copied! Paste it with \u00a7c/{0} paste\u00a76. +editsignCopyLine=\u00a76Copied line \u00a7c{0} \u00a76of sign! Paste it with \u00a7c/{1} paste {0}\u00a76. +editsignPaste=\u00a76Sign pasted! +editsignPasteLine=\u00a76Pasted line \u00a7c{0} \u00a76of sign! +editsignCommandUsage=/ [line number] [text] showkitCommandUsage=/ signFormatFail=\u00a74[{0}] signFormatSuccess=\u00a71[{0}] diff --git a/Essentials/src/main/resources/plugin.yml b/Essentials/src/main/resources/plugin.yml index d4f1fa2bd..cc535b8ce 100644 --- a/Essentials/src/main/resources/plugin.yml +++ b/Essentials/src/main/resources/plugin.yml @@ -426,7 +426,7 @@ commands: aliases: [kitpreview,preview,kitshow] editsign: description: Edits a sign in the world. - usage: / [text] + usage: / [line number] [text] aliases: [sign, esign, eeditsign] skull: description: Set the owner of a player skull