From 51564570ad7df2a57def097860fea8040e3291ea Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Thu, 4 Apr 2024 15:46:12 +0200 Subject: [PATCH] Changes and fixes a lot of things Adds a viewSign command which allows a player to see the entirety of a sign, including any part that overflows the character limit. Changes the save structure for placeholder signs. This change was necessary to support storage of placeholders on both sides of signs, which is also implemented in this commit. Updates Spigot Probably fixes a few bugs --- pom.xml | 2 +- .../placeholdersigns/PlaceholderSigns.java | 116 ++++++++++++------ .../command/EditSignCommand.java | 6 +- .../command/ViewSignCommand.java | 38 ++++++ .../container/PlaceholderSign.java | 26 +--- ...equest.java => SignLineChangeRequest.java} | 3 +- .../handler/PlaceholderSignHandler.java | 115 +++++++++++++---- .../listener/SignBreakListener.java | 3 +- .../listener/SignClickListener.java | 61 ++++++++- .../listener/SignTextListener.java | 14 ++- .../placeholdersigns/util/ColorHelper.java | 3 +- src/main/resources/plugin.yml | 9 +- 12 files changed, 289 insertions(+), 107 deletions(-) create mode 100644 src/main/java/net/knarcraft/placeholdersigns/command/ViewSignCommand.java rename src/main/java/net/knarcraft/placeholdersigns/container/{LineChangeRequest.java => SignLineChangeRequest.java} (71%) diff --git a/pom.xml b/pom.xml index de85bc8..20ab57f 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ org.spigotmc spigot-api - 1.20.1-R0.1-SNAPSHOT + 1.20.4-R0.1-SNAPSHOT provided diff --git a/src/main/java/net/knarcraft/placeholdersigns/PlaceholderSigns.java b/src/main/java/net/knarcraft/placeholdersigns/PlaceholderSigns.java index e8ef9f9..df0f150 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/PlaceholderSigns.java +++ b/src/main/java/net/knarcraft/placeholdersigns/PlaceholderSigns.java @@ -2,8 +2,9 @@ package net.knarcraft.placeholdersigns; import me.clip.placeholderapi.PlaceholderAPI; import net.knarcraft.placeholdersigns.command.EditSignCommand; -import net.knarcraft.placeholdersigns.container.LineChangeRequest; +import net.knarcraft.placeholdersigns.command.ViewSignCommand; import net.knarcraft.placeholdersigns.container.PlaceholderSign; +import net.knarcraft.placeholdersigns.container.SignLineChangeRequest; import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler; import net.knarcraft.placeholdersigns.listener.SignBreakListener; import net.knarcraft.placeholdersigns.listener.SignClickListener; @@ -13,8 +14,8 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Sign; import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; import org.bukkit.command.PluginCommand; -import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -31,7 +32,8 @@ public final class PlaceholderSigns extends JavaPlugin { private static PlaceholderSigns instance; private PlaceholderSignHandler signHandler; - private Map changeRequests; + private Map signChangeRequests; + private Map signViewRequests; /** * Gets an instance of this plugin @@ -59,8 +61,8 @@ public final class PlaceholderSigns extends JavaPlugin { * * @param request

The sign change request to register

*/ - public void addChangeRequest(@NotNull LineChangeRequest request) { - changeRequests.put(request.player(), request); + public void addSignChangeRequest(@NotNull SignLineChangeRequest request) { + signChangeRequests.put(request.player(), request); } /** @@ -69,23 +71,40 @@ public final class PlaceholderSigns extends JavaPlugin { * @param player

The player to get the request for

* @return

The sign change request, or null if not found

*/ - public @Nullable LineChangeRequest getChangeRequest(@NotNull Player player) { - return changeRequests.remove(player); + public @Nullable SignLineChangeRequest getSignChangeRequest(@NotNull Player player) { + return signChangeRequests.remove(player); } - @Override - public void onLoad() { - super.onLoad(); - // Register serialization classes - ConfigurationSerialization.registerClass(PlaceholderSign.class); - ConfigurationSerialization.registerClass(PlaceholderSignHandler.class); + /** + * Registers a sign view request + * + * @param player

The 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 player

The player to check

+ * @return

True 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; + } } @Override public void onEnable() { instance = this; signHandler = new PlaceholderSignHandler(); - changeRequests = new HashMap<>(); + signChangeRequests = new HashMap<>(); + signViewRequests = new HashMap<>(); signHandler.load(); if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") == null) { @@ -105,6 +124,11 @@ public final class PlaceholderSigns extends JavaPlugin { if (editCommand != null) { editCommand.setExecutor(new EditSignCommand()); } + + PluginCommand viewCommand = Bukkit.getPluginCommand("viewSign"); + if (viewCommand != null) { + viewCommand.setExecutor(new ViewSignCommand()); + } } @Override @@ -130,36 +154,52 @@ public final class PlaceholderSigns extends JavaPlugin { } // Update placeholders - Map placeholders = placeholderSign.placeholders(); - String[] lines = sign.getSide(Side.FRONT).getLines(); - boolean updateRequired = false; - for (int i = 0; i < lines.length; i++) { - String oldText = sign.getSide(Side.FRONT).getLine(i); - - // The new text of the sign is either the same, or the original placeholder - String newText; - if (!placeholders.containsKey(i) || placeholders.get(i) == null) { - newText = oldText; - } else { - newText = PlaceholderAPI.setPlaceholders(null, placeholders.get(i)); - } - - // Convert color codes - newText = ColorHelper.translateAllColorCodes(newText); - - // Only change the line if the text has changed - if (!newText.equals(oldText)) { - sign.getSide(Side.FRONT).setLine(i, newText); - updateRequired = true; - } - } + Map> placeholders = placeholderSign.placeholders(); + String[] frontLines = sign.getSide(Side.FRONT).getLines(); + String[] backLines = sign.getSide(Side.BACK).getLines(); // Only update the sign if the text has changed - if (updateRequired) { + if (updatePlaceholders(frontLines, placeholders.get(Side.FRONT), sign.getSide(Side.FRONT)) || + updatePlaceholders(backLines, placeholders.get(Side.BACK), sign.getSide(Side.BACK))) { sign.update(); } } } + /** + * Updates the values of placeholders on a sign + * + * @param lines

The sign's current lines

+ * @param placeholders

The sign's original placeholder lines

+ * @param signSide

The side of the sign to update placeholders for

+ * @return

True if text has been changed, and the sign needs to be updated

+ */ + private boolean updatePlaceholders(@NotNull String[] lines, @NotNull Map placeholders, + @NotNull SignSide signSide) { + boolean changed = false; + for (int i = 0; i < lines.length; i++) { + String oldText = signSide.getLine(i); + + // The new text of the sign is either the same, or the original placeholder + String newText; + if (!placeholders.containsKey(i) || placeholders.get(i) == null) { + newText = oldText; + } else { + newText = PlaceholderAPI.setPlaceholders(null, placeholders.get(i)); + } + + // Convert color codes + newText = ColorHelper.translateAllColorCodes(newText); + + // Only change the line if the text has changed + if (!newText.equals(oldText)) { + signSide.setLine(i, newText); + changed = true; + } + } + + return changed; + } + } diff --git a/src/main/java/net/knarcraft/placeholdersigns/command/EditSignCommand.java b/src/main/java/net/knarcraft/placeholdersigns/command/EditSignCommand.java index 127aaa0..a9d2d15 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/command/EditSignCommand.java +++ b/src/main/java/net/knarcraft/placeholdersigns/command/EditSignCommand.java @@ -1,7 +1,7 @@ package net.knarcraft.placeholdersigns.command; import net.knarcraft.placeholdersigns.PlaceholderSigns; -import net.knarcraft.placeholdersigns.container.LineChangeRequest; +import net.knarcraft.placeholdersigns.container.SignLineChangeRequest; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; @@ -59,8 +59,8 @@ public class EditSignCommand implements TabExecutor { } // Register the line change request - LineChangeRequest request = new LineChangeRequest(player, lineNumber - 1, builder.toString()); - PlaceholderSigns.getInstance().addChangeRequest(request); + SignLineChangeRequest request = new SignLineChangeRequest(player, lineNumber - 1, builder.toString()); + PlaceholderSigns.getInstance().addSignChangeRequest(request); commandSender.sendMessage("Please click the sign you want to change."); return true; diff --git a/src/main/java/net/knarcraft/placeholdersigns/command/ViewSignCommand.java b/src/main/java/net/knarcraft/placeholdersigns/command/ViewSignCommand.java new file mode 100644 index 0000000..5d26722 --- /dev/null +++ b/src/main/java/net/knarcraft/placeholdersigns/command/ViewSignCommand.java @@ -0,0 +1,38 @@ +package net.knarcraft.placeholdersigns.command; + +import net.knarcraft.placeholdersigns.PlaceholderSigns; +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 lines on a sign + */ +public class ViewSignCommand implements TabExecutor { + @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().addSignViewRequest(player); + + commandSender.sendMessage("Please click the sign you want to view."); + return true; + } + + @Nullable + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, + @NotNull String[] args) { + return new ArrayList<>(); + } +} diff --git a/src/main/java/net/knarcraft/placeholdersigns/container/PlaceholderSign.java b/src/main/java/net/knarcraft/placeholdersigns/container/PlaceholderSign.java index eb9da0e..c1306fb 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/container/PlaceholderSign.java +++ b/src/main/java/net/knarcraft/placeholdersigns/container/PlaceholderSign.java @@ -1,10 +1,9 @@ package net.knarcraft.placeholdersigns.container; import org.bukkit.Location; -import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.block.sign.Side; import org.jetbrains.annotations.NotNull; -import java.util.HashMap; import java.util.Map; /** @@ -13,27 +12,6 @@ import java.util.Map; * @param location

The location of the sign

* @param placeholders

The original placeholders typed on the sign

*/ -public record PlaceholderSign(Location location, - Map placeholders) implements ConfigurationSerializable { - - @Override - @NotNull - public Map serialize() { - Map data = new HashMap<>(); - data.put("location", location); - data.put("placeholders", placeholders); - return data; - } - - /** - * Deserializes the placeholder-sign specified in the given data - * - * @param data

The data to deserialize

- * @return

The deserialized placeholder sign

- */ - @SuppressWarnings({"unchecked", "unused"}) - public static PlaceholderSign deserialize(Map data) { - return new PlaceholderSign((Location) data.get("location"), (Map) data.get("placeholders")); - } +public record PlaceholderSign(@NotNull Location location, @NotNull Map> placeholders) { } diff --git a/src/main/java/net/knarcraft/placeholdersigns/container/LineChangeRequest.java b/src/main/java/net/knarcraft/placeholdersigns/container/SignLineChangeRequest.java similarity index 71% rename from src/main/java/net/knarcraft/placeholdersigns/container/LineChangeRequest.java rename to src/main/java/net/knarcraft/placeholdersigns/container/SignLineChangeRequest.java index 6a88bd9..5d09177 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/container/LineChangeRequest.java +++ b/src/main/java/net/knarcraft/placeholdersigns/container/SignLineChangeRequest.java @@ -1,6 +1,7 @@ package net.knarcraft.placeholdersigns.container; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; /** * A record of a player's request to change a sign @@ -9,5 +10,5 @@ import org.bukkit.entity.Player; * @param line

The line the player wants to change

* @param text

The new text the player provided for the line

*/ -public record LineChangeRequest(Player player, int line, String text) { +public record SignLineChangeRequest(@NotNull Player player, int line, @NotNull String text) { } diff --git a/src/main/java/net/knarcraft/placeholdersigns/handler/PlaceholderSignHandler.java b/src/main/java/net/knarcraft/placeholdersigns/handler/PlaceholderSignHandler.java index ed8dff0..fcaeb98 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/handler/PlaceholderSignHandler.java +++ b/src/main/java/net/knarcraft/placeholdersigns/handler/PlaceholderSignHandler.java @@ -2,10 +2,14 @@ package net.knarcraft.placeholdersigns.handler; import net.knarcraft.placeholdersigns.PlaceholderSigns; import net.knarcraft.placeholdersigns.container.PlaceholderSign; +import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.sign.Side; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -13,12 +17,13 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.logging.Level; /** * A handler for keeping track of placeholder signs */ -public class PlaceholderSignHandler implements ConfigurationSerializable { +public class PlaceholderSignHandler { private static final File signsFile = new File(PlaceholderSigns.getInstance().getDataFolder(), "signs.yml"); @@ -40,6 +45,7 @@ public class PlaceholderSignHandler implements ConfigurationSerializable { * @param location

The location of the sign

* @return

The sign at the location, or null if no such sign exists

*/ + @Nullable public PlaceholderSign getFromLocation(@NotNull Location location) { return locationLookup.get(location); } @@ -70,10 +76,58 @@ public class PlaceholderSignHandler implements ConfigurationSerializable { * Loads all placeholder signs from disk */ public void load() { + this.placeholderSigns = new HashSet<>(); + this.locationLookup = new HashMap<>(); + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile); - PlaceholderSignHandler loadedHandler = (PlaceholderSignHandler) configuration.get("signHandler"); - this.placeholderSigns = loadedHandler != null ? loadedHandler.placeholderSigns : new HashSet<>(); - this.locationLookup = loadedHandler != null ? loadedHandler.locationLookup : new HashMap<>(); + ConfigurationSection signSection = configuration.getConfigurationSection("signs"); + if (signSection == null) { + PlaceholderSigns.getInstance().getLogger().log(Level.INFO, "PlaceholderSigns found no signs to load"); + return; + } + + for (String key : signSection.getKeys(false)) { + String[] locationInfo = key.split(","); + World world = Bukkit.getWorld(UUID.fromString(locationInfo[0])); + double x = Integer.parseInt(locationInfo[1]); + double y = Integer.parseInt(locationInfo[2]); + double z = Integer.parseInt(locationInfo[3]); + Location signLocation = new Location(world, x, y, z); + + Map> allPlaceholders = new HashMap<>(); + Map frontPlaceholders = new HashMap<>(); + Map backPlaceholders = new HashMap<>(); + + loadPlaceholders(signSection, key + ".placeholders.front.", frontPlaceholders); + loadPlaceholders(signSection, key + ".placeholders.back.", backPlaceholders); + + allPlaceholders.put(Side.FRONT, frontPlaceholders); + allPlaceholders.put(Side.BACK, backPlaceholders); + + PlaceholderSign sign = new PlaceholderSign(signLocation, allPlaceholders); + this.placeholderSigns.add(sign); + this.locationLookup.put(signLocation, sign); + } + } + + /** + * Loads placeholders from one side of a sign + * + * @param signSection

The configuration section to read

+ * @param configurationKey

The configuration key pointing to the placeholders

+ * @param placeholderMap

The map to add read placeholders to

+ */ + private void loadPlaceholders(@NotNull ConfigurationSection signSection, @NotNull String configurationKey, + @NotNull Map placeholderMap) { + for (int i = 0; i < 4; i++) { + String placeholderKey = configurationKey + i; + if (!signSection.contains(placeholderKey)) { + continue; + } + + String placeholder = signSection.getString(placeholderKey); + placeholderMap.put(i, placeholder); + } } /** @@ -82,37 +136,46 @@ public class PlaceholderSignHandler implements ConfigurationSerializable { public void save() { try { YamlConfiguration configuration = new YamlConfiguration(); - configuration.set("signHandler", this); + ConfigurationSection signsSection = configuration.createSection("signs"); + for (PlaceholderSign sign : placeholderSigns) { + saveSign(signsSection, sign); + } configuration.save(signsFile); } catch (IOException exception) { PlaceholderSigns.getInstance().getLogger().log(Level.SEVERE, "Unable to save placeholder signs!"); } } - @NotNull - @Override - public Map serialize() { - Map data = new HashMap<>(); - data.put("signs", this.placeholderSigns); - return data; - } - /** - * Deserializes the given placeholder sign handler data + * Saves a sign to the given configuration section * - * @param data

The data to deserialize

- * @return

The deserialized sign handler

+ * @param section

The configuration section to save to

+ * @param sign

The sign to save

*/ - @SuppressWarnings({"unchecked", "unused"}) - public static PlaceholderSignHandler deserialize(@NotNull Map data) { - PlaceholderSignHandler placeholderSignHandler = new PlaceholderSignHandler(); - placeholderSignHandler.placeholderSigns = (Set) data.get("signs"); - Map lookup = new HashMap<>(); - for (PlaceholderSign sign : placeholderSignHandler.placeholderSigns) { - lookup.put(sign.location(), sign); + private void saveSign(@NotNull ConfigurationSection section, @NotNull PlaceholderSign sign) { + Location location = sign.location(); + if (location.getWorld() == null) { + return; + } + + String key = location.getWorld().getUID() + "," + location.getBlockX() + "," + location.getBlockY() + + "," + location.getBlockZ(); + String frontKey = key + ".placeholders.front"; + String backKey = key + ".placeholders.back"; + + Map frontPlaceholders = sign.placeholders().get(Side.FRONT); + if (frontPlaceholders != null) { + for (Map.Entry entry : frontPlaceholders.entrySet()) { + section.set(frontKey + "." + entry.getKey(), entry.getValue()); + } + } + + Map backPlaceholders = sign.placeholders().get(Side.BACK); + if (backPlaceholders != null) { + for (Map.Entry entry : backPlaceholders.entrySet()) { + section.set(backKey + "." + entry.getKey(), entry.getValue()); + } } - placeholderSignHandler.locationLookup = lookup; - return placeholderSignHandler; } } diff --git a/src/main/java/net/knarcraft/placeholdersigns/listener/SignBreakListener.java b/src/main/java/net/knarcraft/placeholdersigns/listener/SignBreakListener.java index fac5a37..f750dce 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/listener/SignBreakListener.java +++ b/src/main/java/net/knarcraft/placeholdersigns/listener/SignBreakListener.java @@ -9,6 +9,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; +import org.jetbrains.annotations.NotNull; /** * A listener for placeholder signs being broken @@ -16,7 +17,7 @@ import org.bukkit.event.block.BlockBreakEvent; public class SignBreakListener implements Listener { @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void onSignBreak(BlockBreakEvent event) { + public void onSignBreak(@NotNull BlockBreakEvent event) { Block block = event.getBlock(); if (!(block.getState() instanceof Sign)) { diff --git a/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java b/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java index 113ffa7..57bacf1 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java +++ b/src/main/java/net/knarcraft/placeholdersigns/listener/SignClickListener.java @@ -1,18 +1,22 @@ package net.knarcraft.placeholdersigns.listener; import net.knarcraft.placeholdersigns.PlaceholderSigns; -import net.knarcraft.placeholdersigns.container.LineChangeRequest; +import net.knarcraft.placeholdersigns.container.SignLineChangeRequest; import net.knarcraft.placeholdersigns.util.ColorHelper; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.block.Sign; import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; /** * A listener for placeholder signs being clicked @@ -20,7 +24,7 @@ import org.bukkit.event.player.PlayerInteractEvent; public class SignClickListener implements Listener { @EventHandler(priority = EventPriority.MONITOR) - public void onSignClick(PlayerInteractEvent event) { + public void onSignClick(@NotNull PlayerInteractEvent event) { // Ignore if not a clicked sign if (!event.hasBlock() || event.getClickedBlock() == null || !(event.getClickedBlock().getState() instanceof Sign sign)) { @@ -28,25 +32,70 @@ public class SignClickListener implements Listener { } Player player = event.getPlayer(); + boolean hasSignViewRequest = PlaceholderSigns.getInstance().hasSignViewRequest(player); + if (hasSignViewRequest) { + printSign(sign, player); + } + 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."); return; } // Check if the player has run the /editSign command - LineChangeRequest request = PlaceholderSigns.getInstance().getChangeRequest(player); - if (request == null) { - return; + SignLineChangeRequest request = PlaceholderSigns.getInstance().getSignChangeRequest(player); + if (request != null) { + doSignChange(sign, request, event, player); } + } + /** + * Prints the current contents of a sign to a player + * + * @param sign

The sign to print

+ * @param player

The player to display the contents to

+ */ + 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()); + } + + /** + * Gets text from a sign side, and appends it to the given string builder + * + * @param signSide

The sign side to get text from

+ * @param header

The header to display before printing the sign test

+ * @param builder

The string builder to append the text to

+ */ + private void getSignText(@NotNull SignSide signSide, @NotNull String header, @NotNull StringBuilder builder) { + builder.append(header).append("\n"); + for (int i = 0; i < 4; i++) { + builder.append(signSide.getLine(i)).append("\n"); + } + } + + /** + * Perform the changing of a sign according to the given sign change request + * + * @param sign

The sign to be changed

+ * @param request

The sign line change request to perform

+ * @param event

The interaction event that triggered this

+ * @param player

The player triggering the sign change

+ */ + private void doSignChange(@NotNull Sign sign, @NotNull SignLineChangeRequest request, + @NotNull PlayerInteractEvent event, @NotNull Player player) { // Cancel the event to prevent vanilla behavior event.setCancelled(true); String[] lines = sign.getSide(Side.FRONT).getLines(); + lines[request.line()] = request.text(); // Run the sign change event to allow protection plugins to cancel, and allow the sign text listener to trigger - SignChangeEvent changeEvent = new SignChangeEvent(event.getClickedBlock(), player, lines, Side.FRONT); + SignChangeEvent changeEvent = new SignChangeEvent(Objects.requireNonNull(event.getClickedBlock()), + player, lines, Side.FRONT); Bukkit.getPluginManager().callEvent(changeEvent); if (changeEvent.isCancelled()) { return; diff --git a/src/main/java/net/knarcraft/placeholdersigns/listener/SignTextListener.java b/src/main/java/net/knarcraft/placeholdersigns/listener/SignTextListener.java index bc55b47..6af1d3d 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/listener/SignTextListener.java +++ b/src/main/java/net/knarcraft/placeholdersigns/listener/SignTextListener.java @@ -5,10 +5,12 @@ import net.knarcraft.placeholdersigns.PlaceholderSigns; import net.knarcraft.placeholdersigns.container.PlaceholderSign; import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler; import org.bukkit.Location; +import org.bukkit.block.sign.Side; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.SignChangeEvent; +import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; @@ -19,7 +21,7 @@ import java.util.Map; public class SignTextListener implements Listener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onSignCreateOrEdit(SignChangeEvent event) { + public void onSignCreateOrEdit(@NotNull SignChangeEvent event) { // Only check for placeholders if the player is allowed to if (!event.getPlayer().hasPermission("placeholdersigns.placeholder")) { return; @@ -43,14 +45,16 @@ public class SignTextListener implements Listener { PlaceholderSign existingSign = signHandler.getFromLocation(location); if (!placeholders.isEmpty() && existingSign == null) { + Map> placeholderSide = new HashMap<>(); + placeholderSide.put(event.getSide(), placeholders); + // Register a new placeholder sign - PlaceholderSign placeholderSign = new PlaceholderSign(event.getBlock().getLocation(), placeholders); + PlaceholderSign placeholderSign = new PlaceholderSign(event.getBlock().getLocation(), placeholderSide); signHandler.registerSign(placeholderSign); } else if (!placeholders.isEmpty()) { // Overwrite the placeholders of the existing placeholder sign - for (Map.Entry entry : placeholders.entrySet()) { - existingSign.placeholders().put(entry.getKey(), entry.getValue()); - } + Map existing = existingSign.placeholders().get(event.getSide()); + existing.putAll(placeholders); signHandler.save(); } } diff --git a/src/main/java/net/knarcraft/placeholdersigns/util/ColorHelper.java b/src/main/java/net/knarcraft/placeholdersigns/util/ColorHelper.java index a68107e..a29ebd6 100644 --- a/src/main/java/net/knarcraft/placeholdersigns/util/ColorHelper.java +++ b/src/main/java/net/knarcraft/placeholdersigns/util/ColorHelper.java @@ -1,6 +1,7 @@ package net.knarcraft.placeholdersigns.util; import net.md_5.bungee.api.ChatColor; +import org.jetbrains.annotations.NotNull; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -20,7 +21,7 @@ public final class ColorHelper { * @param message

The string to search for color codes

* @return

The message with color codes translated

*/ - public static String translateAllColorCodes(String message) { + 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); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index cdffed0..8aba459 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -10,6 +10,10 @@ commands: usage: / [text] [text] ... permission: placeholdersigns.edit description: Changes the line of a sign, without a text limit, and with color conversion + viewSign: + usage: / [text] [text] ... + permission: placeholdersigns.view + description: Displays the contents of a sign in the chat (useful for lines exceeding the viewable area) permissions: placeholdersigns.*: @@ -31,4 +35,7 @@ permissions: default: false placeholdersigns.placeholder: description: Allows a player to make signs containing placeholders - default: false \ No newline at end of file + default: false + placeholdersigns.view: + description: Allows a player to see the full text of a sign in the chat + default: true \ No newline at end of file