A plugin instance
*/ - public static @NotNull PlaceholderSigns getInstance() { + @NotNull + public static PlaceholderSigns getInstance() { return instance; } @@ -49,63 +45,38 @@ public final class PlaceholderSigns extends JavaPlugin { * * @returnThe sign handler
*/ - public @NotNull PlaceholderSignHandler getSignHandler() { + @NotNull + public PlaceholderSignHandler getSignHandler() { return this.signHandler; } - /** - * Registers a sign change request - * - *A sign change request is basically the result of running the editSign command, which must be stored until the - * player clicks a sign.
- * - * @param requestThe sign change request to register
- */ - public void addSignChangeRequest(@NotNull SignLineChangeRequest request) { - signChangeRequests.put(request.player(), request); + @NotNull + public PlaceholderSignRequestHandler getRequestHandler() { + return this.requestHandler; } - /** - * Gets a sign change request - * - * @param playerThe player to get the request for
- * @returnThe sign change request, or null if not found
- */ - public @Nullable SignLineChangeRequest getSignChangeRequest(@NotNull Player player) { - return signChangeRequests.remove(player); - } - - /** - * Registers a sign view request - * - * @param playerThe player requesting to view a sign
- */ - public void addSignViewRequest(@NotNull Player player) { - signViewRequests.put(player, null); - } - - /** - * Checks whether the given player has a sign view request - * - * @param playerThe player to check
- * @returnTrue if the player has requested to view a sign
- */ - public boolean hasSignViewRequest(@NotNull Player player) { - if (signViewRequests.containsKey(player)) { - signViewRequests.remove(player); - return true; - } else { - return false; - } + @NotNull + public StringFormatter getStringFormatter() { + return this.stringFormatter; } @Override public void onEnable() { instance = this; - signHandler = new PlaceholderSignHandler(); - signChangeRequests = new HashMap<>(); - signViewRequests = new HashMap<>(); - signHandler.load(); + getConfig().options().copyDefaults(true); + saveConfig(); + Translator translator = new Translator(); + translator.registerMessageCategory(PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_EDIT); + translator.setColorConversion(ColorConversion.RGB); + translator.loadLanguages(this.getDataFolder(), "en", getConfig().getString("language", "en")); + this.stringFormatter = new StringFormatter(this.getDescription().getName(), translator); + this.stringFormatter.setColorConversion(ColorConversion.RGB); + this.stringFormatter.setNamePrefix("#A5682A[&r&l"); + this.stringFormatter.setNameSuffix("&r#A5682A]"); + + this.signHandler = new PlaceholderSignHandler(); + this.signHandler.load(); + this.requestHandler = new PlaceholderSignRequestHandler(); if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") == null) { getLogger().log(Level.WARNING, "Could not find PlaceholderAPI! This plugin is required."); @@ -114,21 +85,15 @@ public final class PlaceholderSigns extends JavaPlugin { } // Update signs' placeholders every second - Bukkit.getScheduler().runTaskTimer(this, this::updateSigns, 20 * 10, 20 * 5); + Bukkit.getScheduler().runTaskTimer(this, new SignUpdate(this.signHandler), 20 * 10, 20 * 5); Bukkit.getPluginManager().registerEvents(new SignBreakListener(), this); Bukkit.getPluginManager().registerEvents(new SignTextListener(), this); Bukkit.getPluginManager().registerEvents(new SignClickListener(), this); - PluginCommand editCommand = Bukkit.getPluginCommand("editSign"); - if (editCommand != null) { - editCommand.setExecutor(new EditSignCommand()); - } - - PluginCommand viewCommand = Bukkit.getPluginCommand("viewSign"); - if (viewCommand != null) { - viewCommand.setExecutor(new ViewSignCommand()); - } + registerCommand("editSign", new EditSignCommand()); + registerCommand("viewSign", new ViewSignCommand(false)); + registerCommand("viewSignRaw", new ViewSignCommand(true)); } @Override @@ -137,77 +102,18 @@ public final class PlaceholderSigns extends JavaPlugin { } /** - * Updates all loaded and registered placeholder signs - */ - private void updateSigns() { - for (PlaceholderSign placeholderSign : signHandler.getSigns()) { - // Ignore signs away from players - Location location = placeholderSign.location(); - if (!location.getChunk().isLoaded()) { - continue; - } - - // If no longer a sign, remove - if (!(location.getBlock().getState() instanceof Sign sign)) { - signHandler.unregisterSign(placeholderSign); - continue; - } - - // Update placeholders - SignSide front = sign.getSide(Side.FRONT); - SignSide back = sign.getSide(Side.BACK); - MapThe sign's current lines
- * @param placeholdersThe sign's original placeholder lines
- * @param signSideThe side of the sign to update placeholders for
- * @returnTrue if text has been changed, and the sign needs to be updated
+ * @param commandNameThe name of the command
+ * @param executorThe command's executor
*/ - private boolean updatePlaceholders(@NotNull String[] lines, @NotNull MapWhether this sign displays the raw text or not
+ */ + public ViewSignCommand(boolean raw) { + this.raw = raw; + } + @Override public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { @@ -23,9 +36,10 @@ public class ViewSignCommand implements TabExecutor { } // Register the sign view request - PlaceholderSigns.getInstance().addSignViewRequest(player); + PlaceholderSigns.getInstance().getRequestHandler().addSignViewRequest(player, this.raw); - commandSender.sendMessage("Please click the sign you want to view."); + PlaceholderSigns.getInstance().getStringFormatter().displaySuccessMessage(commandSender, + PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_VIEW); return true; } @@ -35,4 +49,5 @@ public class ViewSignCommand implements TabExecutor { @NotNull String[] args) { return new ArrayList<>(); } + } diff --git a/src/main/java/net/knarcraft/placeholdersigns/config/PlaceholderSignMessage.java b/src/main/java/net/knarcraft/placeholdersigns/config/PlaceholderSignMessage.java new file mode 100644 index 0000000..5166969 --- /dev/null +++ b/src/main/java/net/knarcraft/placeholdersigns/config/PlaceholderSignMessage.java @@ -0,0 +1,52 @@ +package net.knarcraft.placeholdersigns.config; + +import net.knarcraft.knarlib.formatting.TranslatableMessage; +import org.jetbrains.annotations.NotNull; + +/** + * Translatable plugin messages + */ +public enum PlaceholderSignMessage implements TranslatableMessage { + + /** + * The message to display when waiting for a sign selection (edit) + */ + 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 + */ + ERROR_WAXED_NO_PERMISSION, + + /** + * The message displayed when a sign line has been successfully changed + */ + SUCCESS_SIGN_CHANGED, + + /** + * The format used when printing current sign lines + */ + SUCCESS_SIGN_CONTENTS, + + /** + * The string displayed when a sign is confirmed to be glowing + */ + GLOWING_CONFIRM, + + /** + * The string displayed when a sign is not glowing + */ + GLOWING_DENY, + ; + + @Override + public @NotNull TranslatableMessage[] getAllMessages() { + return PlaceholderSignMessage.values(); + } + +} diff --git a/src/main/java/net/knarcraft/placeholdersigns/handler/PlaceholderSignRequestHandler.java b/src/main/java/net/knarcraft/placeholdersigns/handler/PlaceholderSignRequestHandler.java new file mode 100644 index 0000000..b27d348 --- /dev/null +++ b/src/main/java/net/knarcraft/placeholdersigns/handler/PlaceholderSignRequestHandler.java @@ -0,0 +1,75 @@ +package net.knarcraft.placeholdersigns.handler; + +import net.knarcraft.placeholdersigns.container.SignLineChangeRequest; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** + * A class for keeping track of placeholder sign requests + */ +public class PlaceholderSignRequestHandler { + + private final MapA sign change request is basically the result of running the editSign command, which must be stored until the + * player clicks a sign.
+ * + * @param requestThe sign change request to register
+ */ + public void addSignChangeRequest(@NotNull SignLineChangeRequest request) { + signChangeRequests.put(request.player(), request); + } + + /** + * Gets a sign change request + * + * @param playerThe player to get the request for
+ * @returnThe sign change request, or null if not found
+ */ + @Nullable + public SignLineChangeRequest getSignChangeRequest(@NotNull Player player) { + return signChangeRequests.remove(player); + } + + /** + * Registers a sign view request + * + * @param playerThe player requesting to view a sign
+ * @param rawWhether to display the raw text (visible formatting codes)
+ */ + public void addSignViewRequest(@NotNull Player player, boolean raw) { + signViewRequests.put(player, raw); + } + + /** + * Checks whether the given player has a sign view request + * + * @param playerThe player to check
+ * @returnTrue if the player has requested to view a sign
+ */ + @Nullable + public Boolean getSignViewRequest(@NotNull Player player) { + if (signViewRequests.containsKey(player)) { + return signViewRequests.remove(player); + } else { + return null; + } + } + +} diff --git a/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java b/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java index d65615c..5d96268 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java +++ b/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java @@ -1,10 +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.SignLineChangeRequest; -import net.knarcraft.placeholdersigns.util.ColorHelper; +import net.knarcraft.placeholdersigns.handler.PlaceholderSignRequestHandler; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; +import org.bukkit.DyeColor; import org.bukkit.block.Sign; import org.bukkit.block.sign.Side; import org.bukkit.block.sign.SignSide; @@ -32,18 +38,24 @@ public class SignClickListener implements Listener { } Player player = event.getPlayer(); - boolean hasSignViewRequest = PlaceholderSigns.getInstance().hasSignViewRequest(player); - if (hasSignViewRequest) { - printSign(sign, player); + PlaceholderSignRequestHandler requestHandler = PlaceholderSigns.getInstance().getRequestHandler(); + Boolean hasSignViewRequest = requestHandler.getSignViewRequest(player); + + if (hasSignViewRequest != null) { + printSign(sign, player, hasSignViewRequest); + // Cancel the event to prevent vanilla behavior + event.setCancelled(true); + return; } if (sign.isWaxed() && !player.hasPermission("placeholdersigns.edit.bypass-waxed")) { - player.sendMessage(ChatColor.RED + "You do not have the necessary permissions to edit a waxed sign."); + PlaceholderSigns.getInstance().getStringFormatter().displayErrorMessage(player, + PlaceholderSignMessage.ERROR_WAXED_NO_PERMISSION); return; } // Check if the player has run the /editSign command - SignLineChangeRequest request = PlaceholderSigns.getInstance().getSignChangeRequest(player); + SignLineChangeRequest request = requestHandler.getSignChangeRequest(player); if (request != null) { SignSide standingOn = sign.getTargetSide(player); Side side = sign.getSide(Side.FRONT).equals(standingOn) ? Side.FRONT : Side.BACK; @@ -56,26 +68,80 @@ public class SignClickListener implements Listener { * * @param signThe sign to print
* @param playerThe player to display the contents to
+ * @param rawWhether to get the raw text with used formatting codes
*/ - private void printSign(@NotNull Sign sign, @NotNull Player player) { - StringBuilder builder = new StringBuilder(); - getSignText(sign.getSide(Side.FRONT), "Front:", builder); - getSignText(sign.getSide(Side.BACK), "Back:", builder); - player.sendMessage(builder.toString()); + private void printSign(@NotNull Sign sign, @NotNull Player player, boolean raw) { + SignSide front = sign.getSide(Side.FRONT); + SignSide back = sign.getSide(Side.BACK); + String frontLines = getSignText(front, raw); + String backLines = getSignText(back, 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}", getGlow(front)); + replacer.add("{backDye}", getDye(back)); + replacer.add("{backGlow}", getGlow(back)); + player.sendMessage(replacer.replace()); + } + + /** + * Gets a description of the glow of a sign + * + * @param signSideThe sign side to get the dye of
+ * @returnThe description of the applied dye
+ */ + @NotNull + private String getGlow(@NotNull SignSide signSide) { + boolean glowing = signSide.isGlowingText(); + StringFormatter stringFormatter = PlaceholderSigns.getInstance().getStringFormatter(); + if (glowing) { + return stringFormatter.getUnformattedColoredMessage(PlaceholderSignMessage.GLOWING_CONFIRM); + } else { + return stringFormatter.getUnformattedColoredMessage(PlaceholderSignMessage.GLOWING_DENY); + } + } + + /** + * Gets a description of a dye applied to a sign + * + * @param signSideThe sign side to get the dye of
+ * @returnThe description of the applied dye
+ */ + @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 signSideThe sign side to get text from
- * @param headerThe header to display before printing the sign test
- * @param builderThe string builder to append the text to
+ * @param rawWhether to get the raw text with used formatting codes
*/ - private void getSignText(@NotNull SignSide signSide, @NotNull String header, @NotNull StringBuilder builder) { - builder.append(header).append("\n"); + @NotNull + private String getSignText(@NotNull SignSide signSide, boolean raw) { + StringBuilder output = new StringBuilder(); for (int i = 0; i < 4; i++) { - builder.append(signSide.getLine(i)).append("\n"); + output.append(i + 1).append(". "); + + String line = signSide.getLine(i); + if (raw) { + output.append(line.replace(ChatColor.COLOR_CHAR, '&')); + } else { + output.append(line); + } + output.append("\n"); } + return output.toString(); } /** @@ -107,11 +173,12 @@ public class SignClickListener implements Listener { // Update the sign with the new text String[] finalLines = changeEvent.getLines(); for (int i = 0; i < finalLines.length; i++) { - signSide.setLine(i, ColorHelper.translateAllColorCodes(finalLines[i])); + signSide.setLine(i, ColorHelper.translateColorCodes(finalLines[i], ColorConversion.RGB)); } sign.update(); - player.sendMessage("The sign line was successfully changed."); + PlaceholderSigns.getInstance().getStringFormatter().displaySuccessMessage(player, + PlaceholderSignMessage.SUCCESS_SIGN_CHANGED); } } diff --git a/src/main/java/net/knarcraft/placeholdersigns/runnable/SignUpdate.java b/src/main/java/net/knarcraft/placeholdersigns/runnable/SignUpdate.java new file mode 100644 index 0000000..93cd251 --- /dev/null +++ b/src/main/java/net/knarcraft/placeholdersigns/runnable/SignUpdate.java @@ -0,0 +1,103 @@ +package net.knarcraft.placeholdersigns.runnable; + +import me.clip.placeholderapi.PlaceholderAPI; +import net.knarcraft.knarlib.property.ColorConversion; +import net.knarcraft.knarlib.util.ColorHelper; +import net.knarcraft.placeholdersigns.container.PlaceholderSign; +import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler; +import org.bukkit.Location; +import org.bukkit.block.Sign; +import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +/** + * A runnable that updates signs + */ +public class SignUpdate implements Runnable { + + private final @NotNull PlaceholderSignHandler signHandler; + + /** + * Instantiates a new sign update runnable + * + * @param signHandlerThe sign handler to get signs from
+ */ + public SignUpdate(@NotNull PlaceholderSignHandler signHandler) { + this.signHandler = signHandler; + } + + @Override + public void run() { + for (PlaceholderSign placeholderSign : signHandler.getSigns()) { + // Ignore signs away from players + Location location = placeholderSign.location(); + if (!location.getChunk().isLoaded()) { + continue; + } + + // If no longer a sign, remove + if (!(location.getBlock().getState() instanceof Sign sign)) { + signHandler.unregisterSign(placeholderSign); + continue; + } + + // Update placeholders + SignSide front = sign.getSide(Side.FRONT); + SignSide back = sign.getSide(Side.BACK); + MapThe sign's current lines
+ * @param placeholdersThe sign's original placeholder lines
+ * @param signSideThe side of the sign to update placeholders for
+ * @returnTrue if text has been changed, and the sign needs to be updated
+ */ + private boolean updatePlaceholders(@NotNull String[] lines, @NotNull MapThe string to search for color codes
- * @returnThe message with color codes translated
- */ - public static String translateAllColorCodes(@NotNull String message) { - message = ChatColor.translateAlternateColorCodes('&', message); - Pattern pattern = Pattern.compile("&?(#[a-fA-F0-9]{6})"); - Matcher matcher = pattern.matcher(message); - while (matcher.find()) { - message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group(1))); - } - return message; - } - -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index e69de29..7858036 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -0,0 +1,2 @@ +# The chosen language for PlaceholderSigns. You can use "en" or any custom language specified in strings.yml +language: en \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7cf3169..220cc43 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -14,6 +14,10 @@ commands: usage: /