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.container.PlaceholderSign; import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler; import net.knarcraft.placeholdersigns.listener.SignBreakListener; import net.knarcraft.placeholdersigns.listener.SignClickListener; import net.knarcraft.placeholdersigns.listener.SignTextListener; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Sign; 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; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This plugin's main class */ public final class PlaceholderSigns extends JavaPlugin { private static PlaceholderSigns instance; private PlaceholderSignHandler signHandler; private Map changeRequests; /** * Gets an instance of this plugin * * @return

A plugin instance

*/ public static @NotNull PlaceholderSigns getInstance() { return instance; } /** * Gets this instance's placeholder sign handler * * @return

The sign handler

*/ public @NotNull 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 request

The sign change request to register

*/ public void addChangeRequest(@NotNull LineChangeRequest request) { changeRequests.put(request.player(), request); } /** * Gets a sign change request * * @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); } @Override public void onLoad() { super.onLoad(); // Register serialization classes ConfigurationSerialization.registerClass(PlaceholderSign.class); ConfigurationSerialization.registerClass(PlaceholderSignHandler.class); } @Override public void onEnable() { instance = this; signHandler = new PlaceholderSignHandler(); changeRequests = new HashMap<>(); signHandler.load(); if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") == null) { getLogger().log(Level.WARNING, "Could not find PlaceholderAPI! This plugin is required."); Bukkit.getPluginManager().disablePlugin(this); return; } // Update signs' placeholders every second Bukkit.getScheduler().runTaskTimer(this, this::updateSigns, 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()); } } @Override public void onDisable() { // Plugin shutdown logic } /** * 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 Map placeholders = placeholderSign.placeholders(); String[] lines = sign.getLines(); boolean updateRequired = false; for (int i = 0; i < lines.length; i++) { String oldText = sign.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 = translateAllColorCodes(newText); // Only change the line if the text has changed if (!newText.equals(oldText)) { sign.setLine(i, newText); updateRequired = true; } } // Only update the sign if the text has changed if (updateRequired) { sign.update(); } } } /** * Translates all found color codes to formatting in a string * * @param message

The string to search for color codes

* @return

The message with color codes translated

*/ private static String translateAllColorCodes(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; } }