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 playerThe player to get the request for
* @returnThe 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 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; + } } @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 - 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 location of the sign
* @param placeholdersThe original placeholders typed on the sign
*/ -public record PlaceholderSign(Location location, - MapThe data to deserialize
- * @returnThe deserialized placeholder sign
- */ - @SuppressWarnings({"unchecked", "unused"}) - public static PlaceholderSign deserialize(MapThe line the player wants to change
* @param textThe 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 locationThe location of the sign
* @returnThe 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); + + MapThe configuration section to read
+ * @param configurationKeyThe configuration key pointing to the placeholders
+ * @param placeholderMapThe map to add read placeholders to
+ */ + private void loadPlaceholders(@NotNull ConfigurationSection signSection, @NotNull String configurationKey, + @NotNull MapThe data to deserialize
- * @returnThe deserialized sign handler
+ * @param sectionThe configuration section to save to
+ * @param signThe sign to save
*/ - @SuppressWarnings({"unchecked", "unused"}) - public static PlaceholderSignHandler deserialize(@NotNull MapThe sign to print
+ * @param playerThe 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 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
+ */ + 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 signThe sign to be changed
+ * @param requestThe sign line change request to perform
+ * @param eventThe interaction event that triggered this
+ * @param playerThe 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) { + MapThe string to search for color codes
* @returnThe 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: /