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.PlaceholderSigns; import net.knarcraft.placeholdersigns.container.PlaceholderSign; import net.knarcraft.placeholdersigns.container.QueuedPlaceholderSign; import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler; import net.knarcraft.placeholdersigns.handler.PlaceholderSignUpdateQueueHandler; 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 signHandler

The sign handler to get signs from

*/ public SignUpdate(@NotNull PlaceholderSignHandler signHandler) { this.signHandler = signHandler; } @Override public void run() { PlaceholderSigns instance = PlaceholderSigns.getInstance(); PlaceholderSignUpdateQueueHandler queueHandler = instance.getUpdateQueueHandler(); long startTime = System.nanoTime(); long currentTime = System.currentTimeMillis(); while (queueHandler.peekQueue() != null && System.nanoTime() - startTime < 25000000) { PlaceholderSign placeholderSign = instance.getUpdateQueueHandler().pollQueue(); if (placeholderSign == null) { break; } updatePlaceholderSign(placeholderSign, currentTime); } } /** * Updates the contents of a single placeholder sign * * @param placeholderSign

The placeholder sign to update

* @param currentTime

The current time, used for re-queuing the sign

*/ private void updatePlaceholderSign(@NotNull PlaceholderSign placeholderSign, long currentTime) { PlaceholderSigns instance = PlaceholderSigns.getInstance(); // Ignore signs away from players Location location = placeholderSign.getLocation(); // If no longer a sign, remove if (!(location.getBlock().getState() instanceof Sign sign)) { this.signHandler.unregisterSign(placeholderSign); this.signHandler.save(); return; } // Update placeholders SignSide front = sign.getSide(Side.FRONT); SignSide back = sign.getSide(Side.BACK); Map> placeholders = placeholderSign.getPlaceholders(); String[] frontLines = front.getLines(); String[] backLines = back.getLines(); // Only update the sign if the text has changed boolean updateNecessary = false; if (placeholders.get(Side.FRONT) != null) { updateNecessary |= updatePlaceholders(frontLines, placeholders.get(Side.FRONT), front); } if (placeholders.get(Side.BACK) != null) { updateNecessary |= updatePlaceholders(backLines, placeholders.get(Side.BACK), back); } if (updateNecessary) { sign.update(); } Integer updateDelay = placeholderSign.getUpdateDelay(); if (updateDelay == null) { updateDelay = instance.getSignUpdateDelay(); } instance.getUpdateQueueHandler().queueSign(new QueuedPlaceholderSign(placeholderSign, currentTime + (updateDelay * 50))); } /** * 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.translateColorCodes(newText, ColorConversion.RGB); // Only change the line if the text has changed if (!newText.equals(oldText)) { signSide.setLine(i, newText); changed = true; } } return changed; } }