Adds a copySign command and stuff
All checks were successful
KnarCraft/PlaceholderSigns/pipeline/head This commit looks good
All checks were successful
KnarCraft/PlaceholderSigns/pipeline/head This commit looks good
Adds a new copySign command that copies all info about a sign, including current lines, placeholders, waxed state, dye for each side, and glow state for each side. Renames editSign to setSignLine to avoid collision with EssentialsX's editSign Reduces viewSign to a single command Makes viewSign display the looked at sign, instead of creating a session Adds some additional messages Adds missing documentation to the README
This commit is contained in:
parent
b33f514dca
commit
66c45e00e2
15
README.md
15
README.md
@ -18,15 +18,20 @@ won't be changed unless the player passes all world protection checks.
|
||||
## Commands
|
||||
|
||||
| Command | Arguments | Description |
|
||||
|-----------|-----------------------------|-----------------------------------------------------------------------------------------------|
|
||||
| /editSign | \<line> \<text> \<text> ... | Sets the text of the sign line (1-4) to the given input. Then right-click the sign to update. |
|
||||
|--------------|----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| /setSignLine | \<line> \<text> \<text> ... | Sets the text of the sign line (1-4) to the given input. Then right-click the sign to update. |
|
||||
| /viewSign | \[raw true/false] \[placeholders true/false] | Allows the player to view the full contents and details of the looked at sign. If "raw" is true, formatting codes are displayed. If placeholders is true, stored placeholders are displayed. |
|
||||
| /copySign | | Allows the player to copy the sign they are currently looking at to another sign, including placeholders, formatting codes, dye and waxed state. |
|
||||
|
||||
## Permissions
|
||||
|
||||
| Permission | Description |
|
||||
|------------------------------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| placeholdersigns.* | Gives all permissions. |
|
||||
| placeholdersigns.edit | Allows unrestricted use of the /editSign command. |
|
||||
| placeholdersigns.edit.use | Allows use of the /editSign command. |
|
||||
| placeholdersigns.edit.bypass-waxed | Allows use of the /editSign command on a waxed sign. |
|
||||
| placeholdersigns.edit | Allows unrestricted use of the /setSignLine command. |
|
||||
| placeholdersigns.edit.use | Allows use of the /setSignLine command. |
|
||||
| placeholdersigns.edit.bypass-waxed | Allows use of the /setSignLine command on a waxed sign. |
|
||||
| placeholdersigns.placeholder | Allows a player to make signs containing placeholders. Without this, placeholders are treated as normal text. |
|
||||
| placeholdersigns.copy | Allows unrestricted use of the /copySign command. |
|
||||
| placeholdersigns.copy.use | Allows use of the /copySign command. |
|
||||
| placeholdersigns.copy.bypass-waxed | Allows pasting a sign copied with /copySign onto a waxed sign. |
|
@ -3,8 +3,8 @@ package net.knarcraft.placeholdersigns;
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import net.knarcraft.knarlib.formatting.Translator;
|
||||
import net.knarcraft.knarlib.property.ColorConversion;
|
||||
import net.knarcraft.placeholdersigns.command.CopySignCommand;
|
||||
import net.knarcraft.placeholdersigns.command.EditSignCommand;
|
||||
import net.knarcraft.placeholdersigns.command.ViewPlaceholderSignCommand;
|
||||
import net.knarcraft.placeholdersigns.command.ViewSignCommand;
|
||||
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
|
||||
import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler;
|
||||
@ -92,11 +92,9 @@ public final class PlaceholderSigns extends JavaPlugin {
|
||||
Bukkit.getPluginManager().registerEvents(new SignTextListener(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new SignClickListener(), this);
|
||||
|
||||
registerCommand("editSign", new EditSignCommand());
|
||||
registerCommand("viewSign", new ViewSignCommand(false));
|
||||
registerCommand("viewSignRaw", new ViewSignCommand(true));
|
||||
registerCommand("viewPlaceholderSign", new ViewPlaceholderSignCommand(false));
|
||||
registerCommand("viewPlaceholderSignRaw", new ViewPlaceholderSignCommand(true));
|
||||
registerCommand("setSignLine", new EditSignCommand());
|
||||
registerCommand("viewSign", new ViewSignCommand());
|
||||
registerCommand("copySign", new CopySignCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,54 @@
|
||||
package net.knarcraft.placeholdersigns.command;
|
||||
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
|
||||
import net.knarcraft.placeholdersigns.container.SignCopyRequest;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A command for copying signs, including placeholders
|
||||
*/
|
||||
public class CopySignCommand implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] strings) {
|
||||
PlaceholderSigns placeholderSigns = PlaceholderSigns.getInstance();
|
||||
StringFormatter stringFormatter = placeholderSigns.getStringFormatter();
|
||||
if (!(commandSender instanceof Player player)) {
|
||||
stringFormatter.displayErrorMessage(commandSender, PlaceholderSignMessage.ERROR_PLAYER_ONLY);
|
||||
return false;
|
||||
}
|
||||
|
||||
Block targetBlock = player.getTargetBlockExact(7);
|
||||
if (targetBlock == null || !(targetBlock.getState() instanceof Sign sign)) {
|
||||
stringFormatter.displayErrorMessage(commandSender, PlaceholderSignMessage.ERROR_NOT_LOOKING_AT_SIGN);
|
||||
return false;
|
||||
}
|
||||
|
||||
SignCopyRequest signCopyRequest = new SignCopyRequest(player, sign);
|
||||
placeholderSigns.getRequestHandler().addSignCopyRequest(signCopyRequest);
|
||||
|
||||
stringFormatter.displaySuccessMessage(commandSender, PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_PASTE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] strings) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package net.knarcraft.placeholdersigns.command;
|
||||
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
|
||||
import net.knarcraft.placeholdersigns.container.SignLineChangeRequest;
|
||||
@ -30,7 +31,13 @@ public class EditSignCommand implements TabExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] args) {
|
||||
if (args.length < 1 || !(commandSender instanceof Player player)) {
|
||||
PlaceholderSigns placeholderSigns = PlaceholderSigns.getInstance();
|
||||
StringFormatter stringFormatter = placeholderSigns.getStringFormatter();
|
||||
if (!(commandSender instanceof Player player)) {
|
||||
stringFormatter.displayErrorMessage(commandSender, PlaceholderSignMessage.ERROR_PLAYER_ONLY);
|
||||
return false;
|
||||
}
|
||||
if (args.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -61,11 +68,9 @@ public class EditSignCommand implements TabExecutor {
|
||||
|
||||
// Register the line change request
|
||||
SignLineChangeRequest request = new SignLineChangeRequest(player, lineNumber - 1, builder.toString());
|
||||
PlaceholderSigns placeholderSigns = PlaceholderSigns.getInstance();
|
||||
placeholderSigns.getRequestHandler().addSignChangeRequest(request);
|
||||
|
||||
placeholderSigns.getStringFormatter().displaySuccessMessage(commandSender,
|
||||
PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_EDIT);
|
||||
stringFormatter.displaySuccessMessage(commandSender, PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_EDIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,53 +0,0 @@
|
||||
package net.knarcraft.placeholdersigns.command;
|
||||
|
||||
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A command for viewing placeholders on a sign
|
||||
*/
|
||||
public class ViewPlaceholderSignCommand implements TabExecutor {
|
||||
|
||||
private final boolean raw;
|
||||
|
||||
/**
|
||||
* Instantiates a new view sign command
|
||||
*
|
||||
* @param raw <p>Whether this sign displays the raw text or not</p>
|
||||
*/
|
||||
public ViewPlaceholderSignCommand(boolean raw) {
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
if (!(commandSender instanceof Player player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Register the sign view request
|
||||
PlaceholderSigns.getInstance().getRequestHandler().addPlaceholderSignViewRequest(player, this.raw);
|
||||
|
||||
PlaceholderSigns.getInstance().getStringFormatter().displaySuccessMessage(commandSender,
|
||||
PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_VIEW);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,19 @@
|
||||
package net.knarcraft.placeholdersigns.command;
|
||||
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import net.knarcraft.knarlib.formatting.StringReplacer;
|
||||
import net.knarcraft.knarlib.util.ColorHelper;
|
||||
import net.knarcraft.knarlib.util.TabCompletionHelper;
|
||||
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
|
||||
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.block.sign.SignSide;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
@ -11,43 +23,172 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A command for viewing lines on a sign
|
||||
* A generic sign view command
|
||||
*/
|
||||
public class ViewSignCommand implements TabExecutor {
|
||||
|
||||
private final boolean raw;
|
||||
|
||||
/**
|
||||
* Instantiates a new view sign command
|
||||
*
|
||||
* @param raw <p>Whether this sign displays the raw text or not</p>
|
||||
*/
|
||||
public ViewSignCommand(boolean raw) {
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
@NotNull String[] arguments) {
|
||||
StringFormatter stringFormatter = PlaceholderSigns.getInstance().getStringFormatter();
|
||||
if (!(commandSender instanceof Player player)) {
|
||||
stringFormatter.displayErrorMessage(commandSender, PlaceholderSignMessage.ERROR_PLAYER_ONLY);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Register the sign view request
|
||||
PlaceholderSigns.getInstance().getRequestHandler().addSignViewRequest(player, this.raw);
|
||||
boolean showRawText = true;
|
||||
boolean showPlaceholders = true;
|
||||
if (arguments.length > 0) {
|
||||
showRawText = Boolean.parseBoolean(arguments[0]);
|
||||
}
|
||||
if (arguments.length > 1) {
|
||||
showPlaceholders = Boolean.parseBoolean(arguments[1]);
|
||||
}
|
||||
|
||||
PlaceholderSigns.getInstance().getStringFormatter().displaySuccessMessage(commandSender,
|
||||
PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_VIEW);
|
||||
Block targetBlock = player.getTargetBlockExact(7);
|
||||
if (targetBlock == null || !(targetBlock.getState() instanceof Sign sign)) {
|
||||
stringFormatter.displayErrorMessage(commandSender, PlaceholderSignMessage.ERROR_NOT_LOOKING_AT_SIGN);
|
||||
return false;
|
||||
}
|
||||
|
||||
printSign(sign, player, showRawText, showPlaceholders);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
@NotNull String[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
return getBooleanTabCompletions(arguments[0]);
|
||||
} else if (arguments.length == 2) {
|
||||
return getBooleanTabCompletions(arguments[1]);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets boolean tab-completions
|
||||
*
|
||||
* @param filter <p>The input argument to filter by</p>
|
||||
* @return <p>The the resulting boolean tab-completions</p>
|
||||
*/
|
||||
@NotNull
|
||||
private List<String> getBooleanTabCompletions(@NotNull String filter) {
|
||||
return TabCompletionHelper.filterMatchingStartsWith(List.of("true", "false"), filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the current contents of a sign to a player
|
||||
*
|
||||
* @param sign <p>The sign to print</p>
|
||||
* @param player <p>The player to display the contents to</p>
|
||||
*/
|
||||
private void printSign(@NotNull Sign sign, @NotNull Player player, boolean showRawText, boolean showPlaceholders) {
|
||||
Location location = sign.getLocation();
|
||||
SignSide front = sign.getSide(Side.FRONT);
|
||||
SignSide back = sign.getSide(Side.BACK);
|
||||
String frontLines = showPlaceholders ? getPlaceholderSignText(location, front, Side.FRONT, showRawText) :
|
||||
getSignText(front.getLines(), showRawText);
|
||||
String backLines = showPlaceholders ? getPlaceholderSignText(location, back, Side.BACK, showRawText) :
|
||||
getSignText(back.getLines(), showRawText);
|
||||
|
||||
StringFormatter stringFormatter = PlaceholderSigns.getInstance().getStringFormatter();
|
||||
StringReplacer replacer = new StringReplacer(stringFormatter.getUnformattedColoredMessage(
|
||||
PlaceholderSignMessage.SUCCESS_SIGN_CONTENTS));
|
||||
replacer.add("{frontLines}", frontLines);
|
||||
replacer.add("{backLines}", backLines);
|
||||
replacer.add("{frontDye}", getDye(front));
|
||||
replacer.add("{frontGlow}", getStatus(front.isGlowingText()));
|
||||
replacer.add("{backDye}", getDye(back));
|
||||
replacer.add("{backGlow}", getStatus(back.isGlowingText()));
|
||||
replacer.add("{waxed}", getStatus(sign.isWaxed()));
|
||||
player.sendMessage(replacer.replace());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a description of the status of a sign property
|
||||
*
|
||||
* @param isTrue <p>Whether the property is true</p>
|
||||
* @return <p>A description of the property's current status</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getStatus(boolean isTrue) {
|
||||
StringFormatter stringFormatter = PlaceholderSigns.getInstance().getStringFormatter();
|
||||
if (isTrue) {
|
||||
return stringFormatter.getUnformattedColoredMessage(PlaceholderSignMessage.SIGN_PROPERTY_CONFIRM);
|
||||
} else {
|
||||
return stringFormatter.getUnformattedColoredMessage(PlaceholderSignMessage.SIGN_PROPERTY_DENY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a description of a dye applied to a sign
|
||||
*
|
||||
* @param signSide <p>The sign side to get the dye of</p>
|
||||
* @return <p>The description of the applied dye</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getDye(@NotNull SignSide signSide) {
|
||||
DyeColor dyeColor = signSide.getColor();
|
||||
if (dyeColor == null) {
|
||||
return "None";
|
||||
}
|
||||
|
||||
ChatColor color = ColorHelper.fromColor(dyeColor.getColor());
|
||||
return color + signSide.getColor().name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets text from a sign side, and appends it to the given string builder
|
||||
*
|
||||
* @param signLocation <p>The location of the sign</p>
|
||||
* @param signSide <p>The sign side to get text from</p>
|
||||
* @param side <p>The side of the sign to get placeholders from</p>
|
||||
* @param raw <p>Whether to get the raw text with used formatting codes</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getPlaceholderSignText(@NotNull Location signLocation, @NotNull SignSide signSide,
|
||||
@NotNull Side side, boolean raw) {
|
||||
String[] lines = signSide.getLines();
|
||||
PlaceholderSign placeholderSign = PlaceholderSigns.getInstance().getSignHandler().getFromLocation(signLocation);
|
||||
if (placeholderSign == null) {
|
||||
return getSignText(lines, raw);
|
||||
}
|
||||
|
||||
Map<Integer, String> placeholders = placeholderSign.placeholders().get(side);
|
||||
for (Map.Entry<Integer, String> entry : placeholders.entrySet()) {
|
||||
lines[entry.getKey()] = entry.getValue();
|
||||
}
|
||||
|
||||
return getSignText(lines, raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets text from a sign side, and appends it to the given string builder
|
||||
*
|
||||
* @param lines <p>The lines on the sign</p>
|
||||
* @param raw <p>Whether to get the raw text with used formatting codes</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getSignText(@NotNull String[] lines, boolean raw) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output.append(i + 1).append(". ");
|
||||
|
||||
String line = lines[i];
|
||||
if (raw) {
|
||||
output.append(line.replace(ChatColor.COLOR_CHAR, '&'));
|
||||
} else {
|
||||
output.append(line);
|
||||
}
|
||||
output.append(ChatColor.COLOR_CHAR).append("r\n");
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,11 +13,6 @@ public enum PlaceholderSignMessage implements TranslatableMessage {
|
||||
*/
|
||||
SUCCESS_CLICK_SIGN_TO_EDIT,
|
||||
|
||||
/**
|
||||
* The message to display when waiting for a sign selection (view)
|
||||
*/
|
||||
SUCCESS_CLICK_SIGN_TO_VIEW,
|
||||
|
||||
/**
|
||||
* The message displayed when a player tries to edit a waxed sign without the necessary permission
|
||||
*/
|
||||
@ -42,6 +37,31 @@ public enum PlaceholderSignMessage implements TranslatableMessage {
|
||||
* The string displayed when a sign property is denied
|
||||
*/
|
||||
SIGN_PROPERTY_DENY,
|
||||
|
||||
/**
|
||||
* The message displayed when a player command is used from the console
|
||||
*/
|
||||
ERROR_PLAYER_ONLY,
|
||||
|
||||
/**
|
||||
* The message to display when the player is not looking at a sign, which is required
|
||||
*/
|
||||
ERROR_NOT_LOOKING_AT_SIGN,
|
||||
|
||||
/**
|
||||
* The message displayed when ready to paste a sign
|
||||
*/
|
||||
SUCCESS_CLICK_SIGN_TO_PASTE,
|
||||
|
||||
/**
|
||||
* The message displayed when a sign is successfully pasted
|
||||
*/
|
||||
SUCCESS_SIGN_PASTED,
|
||||
|
||||
/**
|
||||
* The message displayed when a protection plugin cancels the sign change event
|
||||
*/
|
||||
ERROR_CANCELLED_BY_PROTECTION,
|
||||
;
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,14 @@
|
||||
package net.knarcraft.placeholdersigns.container;
|
||||
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A record of a player's request to copy a sign
|
||||
*
|
||||
* @param player <p>The player requesting the sign copy</p>
|
||||
* @param sign <p>The sign the player wants to copy</p>
|
||||
*/
|
||||
public record SignCopyRequest(@NotNull Player player, @NotNull Sign sign) {
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package net.knarcraft.placeholdersigns.handler;
|
||||
|
||||
import net.knarcraft.placeholdersigns.container.SignCopyRequest;
|
||||
import net.knarcraft.placeholdersigns.container.SignLineChangeRequest;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -13,17 +14,38 @@ import java.util.Map;
|
||||
*/
|
||||
public class PlaceholderSignRequestHandler {
|
||||
|
||||
private final Map<Player, SignLineChangeRequest> signChangeRequests;
|
||||
private final Map<Player, Boolean> signViewRequests;
|
||||
private final Map<Player, Boolean> placeholderSignViewRequests;
|
||||
private final @NotNull Map<Player, SignLineChangeRequest> signChangeRequests;
|
||||
private final Map<Player, SignCopyRequest> signCopyRequests;
|
||||
|
||||
/**
|
||||
* Instantiates a new placeholder sign request handler
|
||||
*/
|
||||
public PlaceholderSignRequestHandler() {
|
||||
this.signChangeRequests = new HashMap<>();
|
||||
this.signViewRequests = new HashMap<>();
|
||||
this.placeholderSignViewRequests = new HashMap<>();
|
||||
this.signCopyRequests = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a sign copy request
|
||||
*
|
||||
* <p>A sign copy request is basically the result of running the copySign command, which must be stored until the
|
||||
* player clicks a sign.</p>
|
||||
*
|
||||
* @param request <p>The sign copy request to register</p>
|
||||
*/
|
||||
public void addSignCopyRequest(@NotNull SignCopyRequest request) {
|
||||
this.signCopyRequests.put(request.player(), request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a sign copy request
|
||||
*
|
||||
* @param player <p>The player to get the request for</p>
|
||||
* @return <p>The sign copy request, or null if not found</p>
|
||||
*/
|
||||
@Nullable
|
||||
public SignCopyRequest getSignCopyRequest(@NotNull Player player) {
|
||||
return this.signCopyRequests.remove(player);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,54 +71,4 @@ public class PlaceholderSignRequestHandler {
|
||||
return this.signChangeRequests.remove(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a sign view request
|
||||
*
|
||||
* @param player <p>The player requesting to view a sign</p>
|
||||
* @param raw <p>Whether to display the raw text (visible formatting codes)</p>
|
||||
*/
|
||||
public void addSignViewRequest(@NotNull Player player, boolean raw) {
|
||||
this.signViewRequests.put(player, raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given player has a sign view request
|
||||
*
|
||||
* @param player <p>The player to check</p>
|
||||
* @return <p>Not null if the player has requested to view a sign</p>
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getSignViewRequest(@NotNull Player player) {
|
||||
if (this.signViewRequests.containsKey(player)) {
|
||||
return this.signViewRequests.remove(player);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a placeholder view request
|
||||
*
|
||||
* @param player <p>The player requesting to view a placeholder sign</p>
|
||||
* @param raw <p>Whether to display the raw text (visible formatting codes)</p>
|
||||
*/
|
||||
public void addPlaceholderSignViewRequest(Player player, boolean raw) {
|
||||
this.placeholderSignViewRequests.put(player, raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given player has a placeholder sign view request
|
||||
*
|
||||
* @param player <p>The player to check</p>
|
||||
* @return <p>Not null if the player has requested to view a sign</p>
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getPlaceholderSignViewRequest(@NotNull Player player) {
|
||||
if (this.placeholderSignViewRequests.containsKey(player)) {
|
||||
return this.placeholderSignViewRequests.remove(player);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,19 +1,16 @@
|
||||
package net.knarcraft.placeholdersigns.listener;
|
||||
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import net.knarcraft.knarlib.formatting.StringReplacer;
|
||||
import net.knarcraft.knarlib.property.ColorConversion;
|
||||
import net.knarcraft.knarlib.util.ColorHelper;
|
||||
import net.knarcraft.placeholdersigns.PlaceholderSigns;
|
||||
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
|
||||
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
|
||||
import net.knarcraft.placeholdersigns.container.SignCopyRequest;
|
||||
import net.knarcraft.placeholdersigns.container.SignLineChangeRequest;
|
||||
import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler;
|
||||
import net.knarcraft.placeholdersigns.handler.PlaceholderSignRequestHandler;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.block.sign.SignSide;
|
||||
@ -24,6 +21,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -44,17 +42,13 @@ public class SignClickListener implements Listener {
|
||||
Player player = event.getPlayer();
|
||||
PlaceholderSignRequestHandler requestHandler = PlaceholderSigns.getInstance().getRequestHandler();
|
||||
|
||||
Boolean hasSignViewRequest = requestHandler.getSignViewRequest(player);
|
||||
if (hasSignViewRequest != null) {
|
||||
printSign(sign, player, hasSignViewRequest, false);
|
||||
// Cancel the event to prevent vanilla behavior
|
||||
event.setCancelled(true);
|
||||
SignCopyRequest signCopyRequest = requestHandler.getSignCopyRequest(player);
|
||||
if (signCopyRequest != null) {
|
||||
if (checkWaxEdit(sign, player, "placeholdersigns.copy.bypass-waxed")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Boolean hasPlaceholderSignViewRequest = requestHandler.getPlaceholderSignViewRequest(player);
|
||||
if (hasPlaceholderSignViewRequest != null) {
|
||||
printSign(sign, player, hasPlaceholderSignViewRequest, true);
|
||||
pasteSign(signCopyRequest.sign(), sign, player);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
@ -62,9 +56,7 @@ public class SignClickListener implements Listener {
|
||||
// Check if the player has run the /editSign command
|
||||
SignLineChangeRequest request = requestHandler.getSignChangeRequest(player);
|
||||
if (request != null) {
|
||||
if (sign.isWaxed() && !player.hasPermission("placeholdersigns.edit.bypass-waxed")) {
|
||||
PlaceholderSigns.getInstance().getStringFormatter().displayErrorMessage(player,
|
||||
PlaceholderSignMessage.ERROR_WAXED_NO_PERMISSION);
|
||||
if (checkWaxEdit(sign, player, "placeholdersigns.edit.bypass-waxed")) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -75,114 +67,138 @@ public class SignClickListener implements Listener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the current contents of a sign to a player
|
||||
* Checks if the player is trying to edit/modify a waxed sign without permission
|
||||
*
|
||||
* @param sign <p>The sign to print</p>
|
||||
* @param player <p>The player to display the contents to</p>
|
||||
* @param raw <p>Whether to get the raw text with used formatting codes</p>
|
||||
* @param showPlaceholders <p>Whether to show the actual placeholders stored on the sign</p>
|
||||
* @param sign <p>The sign the player is trying to edit</p>
|
||||
* @param player <p>The player trying to edit the sign</p>
|
||||
* @return <p>True if the player is trying to edit a waxed sign without permission</p>
|
||||
*/
|
||||
private void printSign(@NotNull Sign sign, @NotNull Player player, boolean raw, boolean showPlaceholders) {
|
||||
Location location = sign.getLocation();
|
||||
SignSide front = sign.getSide(Side.FRONT);
|
||||
SignSide back = sign.getSide(Side.BACK);
|
||||
String frontLines = showPlaceholders ? getPlaceholderSignText(location, front, Side.FRONT, raw) :
|
||||
getSignText(front.getLines(), raw);
|
||||
String backLines = showPlaceholders ? getPlaceholderSignText(location, back, Side.BACK, raw) :
|
||||
getSignText(back.getLines(), raw);
|
||||
|
||||
StringFormatter stringFormatter = PlaceholderSigns.getInstance().getStringFormatter();
|
||||
StringReplacer replacer = new StringReplacer(stringFormatter.getUnformattedColoredMessage(
|
||||
PlaceholderSignMessage.SUCCESS_SIGN_CONTENTS));
|
||||
replacer.add("{frontLines}", frontLines);
|
||||
replacer.add("{backLines}", backLines);
|
||||
replacer.add("{frontDye}", getDye(front));
|
||||
replacer.add("{frontGlow}", getStatus(front.isGlowingText()));
|
||||
replacer.add("{backDye}", getDye(back));
|
||||
replacer.add("{backGlow}", getStatus(back.isGlowingText()));
|
||||
replacer.add("{waxed}", getStatus(sign.isWaxed()));
|
||||
player.sendMessage(replacer.replace());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a description of the status of a sign property
|
||||
*
|
||||
* @param isTrue <p>Whether the property is true</p>
|
||||
* @return <p>A description of the property's current status</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getStatus(boolean isTrue) {
|
||||
StringFormatter stringFormatter = PlaceholderSigns.getInstance().getStringFormatter();
|
||||
if (isTrue) {
|
||||
return stringFormatter.getUnformattedColoredMessage(PlaceholderSignMessage.SIGN_PROPERTY_CONFIRM);
|
||||
private boolean checkWaxEdit(@NotNull Sign sign, @NotNull Player player, @NotNull String permissionNode) {
|
||||
if (sign.isWaxed() && !player.hasPermission(permissionNode)) {
|
||||
PlaceholderSigns.getInstance().getStringFormatter().displayErrorMessage(player,
|
||||
PlaceholderSignMessage.ERROR_WAXED_NO_PERMISSION);
|
||||
return true;
|
||||
} else {
|
||||
return stringFormatter.getUnformattedColoredMessage(PlaceholderSignMessage.SIGN_PROPERTY_DENY);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a description of a dye applied to a sign
|
||||
* Pastes the data from the source sign to the target sign
|
||||
*
|
||||
* @param signSide <p>The sign side to get the dye of</p>
|
||||
* @return <p>The description of the applied dye</p>
|
||||
* @param source <p>The source sign to copy data from</p>
|
||||
* @param target <p>The target sign to paste to</p>
|
||||
* @param player <p>The player pasting the sign</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getDye(@NotNull SignSide signSide) {
|
||||
DyeColor dyeColor = signSide.getColor();
|
||||
if (dyeColor == null) {
|
||||
return "None";
|
||||
private void pasteSign(@NotNull Sign source, @NotNull Sign target, @NotNull Player player) {
|
||||
StringFormatter stringFormatter = PlaceholderSigns.getInstance().getStringFormatter();
|
||||
PlaceholderSign placeholderSign = PlaceholderSigns.getInstance().getSignHandler().getFromLocation(source.getLocation());
|
||||
SignSide sourceFront = source.getSide(Side.FRONT);
|
||||
SignSide sourceBack = source.getSide(Side.BACK);
|
||||
SignSide targetFront = target.getSide(Side.FRONT);
|
||||
SignSide targetBack = target.getSide(Side.BACK);
|
||||
|
||||
// Get the lines, with placeholders replaced, and the sign change event processed
|
||||
String[] frontLines = getFinalLines(target, sourceFront, Side.FRONT, placeholderSign, player);
|
||||
if (frontLines == null) {
|
||||
stringFormatter.displayErrorMessage(player, PlaceholderSignMessage.ERROR_CANCELLED_BY_PROTECTION);
|
||||
return;
|
||||
}
|
||||
String[] backLines = getFinalLines(target, sourceBack, Side.BACK, placeholderSign, player);
|
||||
if (backLines == null) {
|
||||
stringFormatter.displayErrorMessage(player, PlaceholderSignMessage.ERROR_CANCELLED_BY_PROTECTION);
|
||||
return;
|
||||
}
|
||||
|
||||
ChatColor color = ColorHelper.fromColor(dyeColor.getColor());
|
||||
return color + signSide.getColor().name();
|
||||
// Update the lines on both sides of the target sign
|
||||
for (int i = 0; i < frontLines.length; i++) {
|
||||
targetFront.setLine(i, ColorHelper.translateColorCodes(frontLines[i], ColorConversion.RGB));
|
||||
}
|
||||
for (int i = 0; i < backLines.length; i++) {
|
||||
targetBack.setLine(i, ColorHelper.translateColorCodes(backLines[i], ColorConversion.RGB));
|
||||
}
|
||||
|
||||
// Copy options
|
||||
copySignOptions(source, target);
|
||||
|
||||
// Apply changes
|
||||
target.update();
|
||||
|
||||
stringFormatter.displaySuccessMessage(player, PlaceholderSignMessage.SUCCESS_SIGN_PASTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets text from a sign side, and appends it to the given string builder
|
||||
* Gets the final lines from a sign side, after inserting placeholders and running a sign change event
|
||||
*
|
||||
* @param signLocation <p>The location of the sign</p>
|
||||
* @param signSide <p>The sign side to get text from</p>
|
||||
* @param side <p>The side of the sign to get placeholders from</p>
|
||||
* @param raw <p>Whether to get the raw text with used formatting codes</p>
|
||||
* @param sign <p>The sign that's changed</p>
|
||||
* @param signSide <p>The side of the sign to get lines from</p>
|
||||
* @param side <p>The side that's processed</p>
|
||||
* @param placeholderSign <p>The placeholder sign corresponding to the sign, if any</p>
|
||||
* @param player <p>The player attempting to paste the sign</p>
|
||||
* @return <p>The final lines, or null if the event was cancelled</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getPlaceholderSignText(@NotNull Location signLocation, @NotNull SignSide signSide,
|
||||
@NotNull Side side, boolean raw) {
|
||||
String[] lines = signSide.getLines();
|
||||
PlaceholderSign placeholderSign = PlaceholderSigns.getInstance().getSignHandler().getFromLocation(signLocation);
|
||||
if (placeholderSign == null) {
|
||||
return getSignText(lines, raw);
|
||||
@Nullable
|
||||
private String[] getFinalLines(@NotNull Sign sign, @NotNull SignSide signSide, @NotNull Side side,
|
||||
@Nullable PlaceholderSign placeholderSign, @NotNull Player player) {
|
||||
String[] sideLines = signSide.getLines();
|
||||
if (placeholderSign != null) {
|
||||
Map<Side, Map<Integer, String>> placeholders = placeholderSign.placeholders();
|
||||
loadPlaceholders(side, sideLines, placeholders);
|
||||
}
|
||||
|
||||
Map<Integer, String> placeholders = placeholderSign.placeholders().get(side);
|
||||
for (Map.Entry<Integer, String> entry : placeholders.entrySet()) {
|
||||
lines[entry.getKey()] = entry.getValue();
|
||||
// Run the sign change event to allow protection plugins to cancel, and allow the sign text listener to trigger
|
||||
SignChangeEvent changeEvent = new SignChangeEvent(Objects.requireNonNull(sign.getBlock()), player, sideLines, side);
|
||||
Bukkit.getPluginManager().callEvent(changeEvent);
|
||||
if (changeEvent.isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getSignText(lines, raw);
|
||||
return changeEvent.getLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets text from a sign side, and appends it to the given string builder
|
||||
* Copies all sign option (dye, glowing, waxed) from the source to the target
|
||||
*
|
||||
* @param lines <p>The lines on the sign</p>
|
||||
* @param raw <p>Whether to get the raw text with used formatting codes</p>
|
||||
* @param source <p>The source sign</p>
|
||||
* @param target <p>The target sign</p>
|
||||
*/
|
||||
@NotNull
|
||||
private String getSignText(@NotNull String[] lines, boolean raw) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
private void copySignOptions(@NotNull Sign source, @NotNull Sign target) {
|
||||
SignSide sourceFront = source.getSide(Side.FRONT);
|
||||
SignSide sourceBack = source.getSide(Side.BACK);
|
||||
SignSide targetFront = target.getSide(Side.FRONT);
|
||||
SignSide targetBack = target.getSide(Side.BACK);
|
||||
|
||||
// Copy glowing state
|
||||
targetFront.setGlowingText(sourceFront.isGlowingText());
|
||||
targetBack.setGlowingText(sourceBack.isGlowingText());
|
||||
|
||||
// Copy applied dye
|
||||
targetFront.setColor(sourceFront.getColor());
|
||||
targetBack.setColor(sourceBack.getColor());
|
||||
|
||||
// Apply waxed state
|
||||
target.setWaxed(source.isWaxed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads placeholders from one side of a sign
|
||||
*
|
||||
* @param side <p>The side to load from</p>
|
||||
* @param lines <p>The array to write placeholders to</p>
|
||||
* @param placeholders <p>The placeholders to load</p>
|
||||
*/
|
||||
private void loadPlaceholders(@NotNull Side side, @NotNull String[] lines,
|
||||
@NotNull Map<Side, Map<Integer, String>> placeholders) {
|
||||
if (!placeholders.containsKey(side)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Integer, String> sidePlaceholders = placeholders.get(side);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output.append(i + 1).append(". ");
|
||||
|
||||
String line = lines[i];
|
||||
if (raw) {
|
||||
output.append(line.replace(ChatColor.COLOR_CHAR, '&'));
|
||||
} else {
|
||||
output.append(line);
|
||||
if (sidePlaceholders.containsKey(i)) {
|
||||
lines[i] = sidePlaceholders.get(i);
|
||||
}
|
||||
output.append(ChatColor.COLOR_CHAR).append("r\n");
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,6 +236,8 @@ public class SignClickListener implements Listener {
|
||||
// Restore the old placeholder if the action didn't complete
|
||||
placeholderSign.placeholders().get(side).put(request.line(), oldPlaceholder);
|
||||
}
|
||||
PlaceholderSigns.getInstance().getStringFormatter().displayErrorMessage(player,
|
||||
PlaceholderSignMessage.ERROR_CANCELLED_BY_PROTECTION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6,33 +6,27 @@ depend:
|
||||
- PlaceholderAPI
|
||||
|
||||
commands:
|
||||
editSign:
|
||||
setSignLine:
|
||||
usage: /<command> <line> [text] [text] ...
|
||||
permission: placeholdersigns.edit
|
||||
permission: placeholdersigns.edit.use
|
||||
description: Changes the line of a sign, without a text limit, and with color conversion
|
||||
viewSign:
|
||||
usage: /<command>
|
||||
usage: /<command> [output raw formatting codes (true/false)] [show placeholders (true/false)]
|
||||
permission: placeholdersigns.view
|
||||
description: Displays the contents of a sign in the chat (useful for lines exceeding the viewable area)
|
||||
viewSignRaw:
|
||||
copySign:
|
||||
usage: /<command>
|
||||
permission: placeholdersigns.view
|
||||
description: Displays the raw contents of a sign in the chat (useful for lines exceeding the viewable area, or to see formatting used)
|
||||
viewPlaceholderSign:
|
||||
usage: /<command>
|
||||
permission: placeholdersigns.view
|
||||
description: Displays the contents of a sign in the chat, including stored placeholders
|
||||
viewPlaceholderSignRaw:
|
||||
usage: /<command>
|
||||
permission: placeholdersigns.view
|
||||
description: Displays the raw contents of a sign in the chat, including stored placeholders
|
||||
permission: placeholdersigns.copy.use
|
||||
description: Copies all sign information from one sign to another
|
||||
|
||||
permissions:
|
||||
placeholdersigns.*:
|
||||
description: Grants all placeholdersigns permissions
|
||||
children:
|
||||
- placeholdersigns.edit
|
||||
- placeholdersigns.placeholder
|
||||
- placeholdersigns.view
|
||||
- placeholdersigns.copy
|
||||
default: op
|
||||
placeholdersigns.edit:
|
||||
description: Allows a player to use the /editSign command without restriction
|
||||
@ -40,6 +34,12 @@ permissions:
|
||||
children:
|
||||
- placeholdersigns.edit.use
|
||||
- placeholdersigns.edit.bypass-waxed
|
||||
placeholdersigns.copy:
|
||||
description: Allows a player to copy a sign to another sign
|
||||
default: false
|
||||
children:
|
||||
- placeholdersigns.copy.use
|
||||
- placeholdersigns.copy.bypass-waxed
|
||||
placeholdersigns.edit.use:
|
||||
description: Allows a player to use the /editSign command
|
||||
default: false
|
||||
@ -52,3 +52,9 @@ permissions:
|
||||
placeholdersigns.view:
|
||||
description: Allows a player to see the full text of a sign in the chat
|
||||
default: true
|
||||
placeholdersigns.copy.use:
|
||||
description: Allows a player to copy a sign to another sign
|
||||
default: false
|
||||
placeholdersigns.copy.bypass-waxed:
|
||||
description: Allows a player to use the /copySign command and paste onto a waxed sign
|
||||
default: false
|
@ -1,8 +1,7 @@
|
||||
en:
|
||||
SUCCESS_CLICK_SIGN_TO_EDIT: "Please click the sign you want to change."
|
||||
SUCCESS_CLICK_SIGN_TO_VIEW: "Please click the sign you want to view."
|
||||
SUCCESS_CLICK_SIGN_TO_EDIT: "&7Please click the sign you want to change."
|
||||
ERROR_WAXED_NO_PERMISSION: "You do not have the necessary permissions to edit a waxed sign."
|
||||
SUCCESS_SIGN_CHANGED: "The sign line was successfully changed."
|
||||
SUCCESS_SIGN_CHANGED: "&7The sign line was successfully changed."
|
||||
SUCCESS_SIGN_CONTENTS: |
|
||||
#78da55&lSign contents:&r
|
||||
#17A057Front:&r
|
||||
@ -14,3 +13,8 @@ en:
|
||||
#ffdf32Waxed {waxed}
|
||||
SIGN_PROPERTY_CONFIRM: "#FDFFC8Yes"
|
||||
SIGN_PROPERTY_DENY: "#CAC8FFNo"
|
||||
ERROR_PLAYER_ONLY: "This command must be used by a player"
|
||||
ERROR_NOT_LOOKING_AT_SIGN: "You are not currently looking at a sign"
|
||||
SUCCESS_CLICK_SIGN_TO_PASTE: "&7Click the sign you want to paste onto"
|
||||
SUCCESS_SIGN_PASTED: "&7Sign pasted!"
|
||||
ERROR_CANCELLED_BY_PROTECTION: "A protection plugin blocked the sign change"
|
Loading…
Reference in New Issue
Block a user