Implements #1
All checks were successful
KnarCraft/PlaceholderSigns/pipeline/head This commit looks good

This commit is contained in:
2024-04-30 03:09:47 +02:00
parent a34c63b7e2
commit f8ca5705a5
18 changed files with 489 additions and 76 deletions

View File

@@ -6,11 +6,14 @@ import net.knarcraft.knarlib.property.ColorConversion;
import net.knarcraft.placeholdersigns.command.CopySignCommand;
import net.knarcraft.placeholdersigns.command.CopySignTextCommand;
import net.knarcraft.placeholdersigns.command.EditSignCommand;
import net.knarcraft.placeholdersigns.command.SetPlaceholderUpdateDelayCommand;
import net.knarcraft.placeholdersigns.command.UnWaxSignCommand;
import net.knarcraft.placeholdersigns.command.ViewSignCommand;
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler;
import net.knarcraft.placeholdersigns.handler.PlaceholderSignRequestHandler;
import net.knarcraft.placeholdersigns.handler.PlaceholderSignUpdateQueueHandler;
import net.knarcraft.placeholdersigns.listener.ChunkListener;
import net.knarcraft.placeholdersigns.listener.SignBreakListener;
import net.knarcraft.placeholdersigns.listener.SignClickListener;
import net.knarcraft.placeholdersigns.listener.SignTextListener;
@@ -18,6 +21,7 @@ import net.knarcraft.placeholdersigns.runnable.SignUpdate;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@@ -31,7 +35,9 @@ public final class PlaceholderSigns extends JavaPlugin {
private static PlaceholderSigns instance;
private PlaceholderSignHandler signHandler;
private PlaceholderSignRequestHandler requestHandler;
private PlaceholderSignUpdateQueueHandler updateQueueHandler;
private StringFormatter stringFormatter;
private int signUpdateDelay;
/**
* Gets an instance of this plugin
@@ -53,21 +59,51 @@ public final class PlaceholderSigns extends JavaPlugin {
return this.signHandler;
}
/**
* Gets this instance's placeholder sign request handler
*
* @return <p>The request handler</p>
*/
@NotNull
public PlaceholderSignRequestHandler getRequestHandler() {
return this.requestHandler;
}
/**
* Gets this instance's update queue handler
*
* @return <p>The update queue handler</p>
*/
@NotNull
public PlaceholderSignUpdateQueueHandler getUpdateQueueHandler() {
return this.updateQueueHandler;
}
/**
* Gets the string formatter to use for formatting messages
*
* @return <p>The string formatter</p>
*/
@NotNull
public StringFormatter getStringFormatter() {
return this.stringFormatter;
}
/**
* Gets the default sign update delay
*
* @return <p>The sign update delay</p>
*/
public int getSignUpdateDelay() {
return this.signUpdateDelay;
}
@Override
public void onEnable() {
instance = this;
getConfig().options().copyDefaults(true);
saveConfig();
Translator translator = new Translator();
translator.registerMessageCategory(PlaceholderSignMessage.SUCCESS_CLICK_SIGN_TO_EDIT);
translator.setColorConversion(ColorConversion.RGB);
@@ -77,9 +113,15 @@ public final class PlaceholderSigns extends JavaPlugin {
this.stringFormatter.setNamePrefix("#A5682A[&r&l");
this.stringFormatter.setNameSuffix("&r#A5682A]");
signUpdateDelay = getConfig().getInt("defaultSignUpdateTicks", 100);
if (signUpdateDelay < 1) {
signUpdateDelay = 100;
}
this.signHandler = new PlaceholderSignHandler();
this.signHandler.load();
this.requestHandler = new PlaceholderSignRequestHandler();
this.updateQueueHandler = new PlaceholderSignUpdateQueueHandler();
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") == null) {
getLogger().log(Level.WARNING, "Could not find PlaceholderAPI! This plugin is required.");
@@ -87,18 +129,20 @@ public final class PlaceholderSigns extends JavaPlugin {
return;
}
// Update signs' placeholders every second
Bukkit.getScheduler().runTaskTimer(this, new SignUpdate(this.signHandler), 20 * 10, 20 * 5);
Bukkit.getScheduler().runTaskTimer(this, new SignUpdate(this.signHandler), 20, 1);
Bukkit.getPluginManager().registerEvents(new SignBreakListener(), this);
Bukkit.getPluginManager().registerEvents(new SignTextListener(), this);
Bukkit.getPluginManager().registerEvents(new SignClickListener(), this);
PluginManager pluginManager = Bukkit.getPluginManager();
pluginManager.registerEvents(new SignBreakListener(), this);
pluginManager.registerEvents(new SignTextListener(), this);
pluginManager.registerEvents(new SignClickListener(), this);
pluginManager.registerEvents(new ChunkListener(), this);
registerCommand("setSignLine", new EditSignCommand());
registerCommand("viewSign", new ViewSignCommand());
registerCommand("copySign", new CopySignCommand());
registerCommand("unWaxSign", new UnWaxSignCommand());
registerCommand("copySignText", new CopySignTextCommand());
registerCommand("setPlaceholderUpdateDelay", new SetPlaceholderUpdateDelayCommand());
}
@Override

View File

@@ -0,0 +1,77 @@
package net.knarcraft.placeholdersigns.command;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.util.TabCompletionHelper;
import net.knarcraft.placeholdersigns.PlaceholderSigns;
import net.knarcraft.placeholdersigns.config.PlaceholderSignMessage;
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
import net.knarcraft.placeholdersigns.handler.PlaceholderSignHandler;
import net.knarcraft.placeholdersigns.util.TabCompleteHelper;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
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;
public class SetPlaceholderUpdateDelayCommand implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] arguments) {
PlaceholderSigns placeholderSigns = PlaceholderSigns.getInstance();
StringFormatter stringFormatter = placeholderSigns.getStringFormatter();
if (!(commandSender instanceof Player player)) {
stringFormatter.displayErrorMessage(commandSender, PlaceholderSignMessage.ERROR_PLAYER_ONLY);
return false;
}
if (arguments.length < 1) {
return false;
}
Block targetBlock = player.getTargetBlockExact(7);
if (targetBlock == null || !(targetBlock.getState() instanceof Sign sign)) {
stringFormatter.displayErrorMessage(commandSender, PlaceholderSignMessage.ERROR_NOT_LOOKING_AT_SIGN);
return false;
}
Integer updateDelay = null;
try {
updateDelay = Integer.parseInt(arguments[0]);
} catch (NumberFormatException exception) {
if (!arguments[0].equalsIgnoreCase("null")) {
return false;
}
}
PlaceholderSignHandler signHandler = placeholderSigns.getSignHandler();
PlaceholderSign placeholderSign = signHandler.getFromLocation(sign.getLocation());
if (placeholderSign != null) {
placeholderSign.setUpdateDelay(updateDelay);
signHandler.save();
stringFormatter.displaySuccessMessage(player, PlaceholderSignMessage.SUCCESS_UPDATE_DELAY_CHANGED);
return true;
} else {
stringFormatter.displayErrorMessage(player, PlaceholderSignMessage.ERROR_NOT_LOOKING_AT_PLACEHOLDER_SIGN);
return false;
}
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] arguments) {
if (arguments.length == 1) {
return TabCompletionHelper.filterMatchingStartsWith(TabCompleteHelper.getDelays(), arguments[0]);
} else {
return new ArrayList<>();
}
}
}

View File

@@ -160,7 +160,7 @@ public class ViewSignCommand implements TabExecutor {
return getSignText(lines, raw);
}
Map<Integer, String> placeholders = placeholderSign.placeholders().get(side);
Map<Integer, String> placeholders = placeholderSign.getPlaceholders().get(side);
if (placeholders != null) {
for (Map.Entry<Integer, String> entry : placeholders.entrySet()) {
lines[entry.getKey()] = entry.getValue();

View File

@@ -67,6 +67,16 @@ public enum PlaceholderSignMessage implements TranslatableMessage {
* The message displayed when a sign has been successfully un-waxed
*/
SUCCESS_SIGN_UN_WAXED,
/**
* The message displayed when the player isn't looking at a placeholder sign when required
*/
ERROR_NOT_LOOKING_AT_PLACEHOLDER_SIGN,
/**
* The message displayed when a placeholder sign update delay has been changed
*/
SUCCESS_UPDATE_DELAY_CHANGED,
;
@Override

View File

@@ -3,15 +3,78 @@ package net.knarcraft.placeholdersigns.container;
import org.bukkit.Location;
import org.bukkit.block.sign.Side;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
/**
* A sign containing one or more placeholders
*
* @param location <p>The location of the sign</p>
* @param placeholders <p>The original placeholders typed on the sign</p>
*/
public record PlaceholderSign(@NotNull Location location, @NotNull Map<Side, Map<Integer, String>> placeholders) {
public final class PlaceholderSign {
private final @NotNull Location location;
private final @NotNull Map<Side, Map<Integer, String>> placeholders;
private @Nullable Integer updateDelay;
/**
* Instantiates a new placeholder sign
*
* @param location <p>The location of the sign</p>
* @param placeholders <p>The original placeholders typed on the sign</p>
* @param updateDelay <p>The delay in ticks between each time this sign's placeholders are updated</p>
*/
public PlaceholderSign(@NotNull Location location, @NotNull Map<Side, Map<Integer, String>> placeholders,
@Nullable Integer updateDelay) {
this.location = location;
this.placeholders = placeholders;
this.updateDelay = updateDelay;
}
/**
* Gets the location of this placeholder sign
*
* @return <p>The location of this placeholder sign</p>
*/
@NotNull
public Location getLocation() {
return location;
}
/**
* Gets the placeholders stored on this sign
*
* @return <p>The stored placeholders</p>
*/
@NotNull
public Map<Side, Map<Integer, String>> getPlaceholders() {
return placeholders;
}
/**
* Gets the update delay for this placeholder sign
*
* @return <p>The update delay</p>
*/
@Nullable
public Integer getUpdateDelay() {
return updateDelay;
}
/**
* Sets the update delay for this placeholder sign
*
* @param updateDelay <p>The new update delay</p>
*/
public void setUpdateDelay(@Nullable Integer updateDelay) {
this.updateDelay = updateDelay;
}
@Override
public boolean equals(@NotNull Object object) {
if (object instanceof PlaceholderSign otherSign) {
return this.location.equals(otherSign.location);
}
return false;
}
}

View File

@@ -0,0 +1,19 @@
package net.knarcraft.placeholdersigns.container;
import org.jetbrains.annotations.NotNull;
/**
* A placeholder sign that's queued to be updated
*
* @param placeholderSign <p>The queued placeholder sign</p>
* @param updateTimestamp <p>The timestamp (long milliseconds) that the placeholder sign should be updated at</p>
*/
public record QueuedPlaceholderSign(@NotNull PlaceholderSign placeholderSign,
long updateTimestamp) implements Comparable<QueuedPlaceholderSign> {
@Override
public int compareTo(@NotNull QueuedPlaceholderSign other) {
return Long.compare(this.updateTimestamp, other.updateTimestamp);
}
}

View File

@@ -3,6 +3,7 @@ package net.knarcraft.placeholdersigns.handler;
import net.knarcraft.placeholdersigns.PlaceholderSigns;
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.sign.Side;
@@ -29,15 +30,7 @@ public class PlaceholderSignHandler {
private Set<PlaceholderSign> placeholderSigns;
private Map<Location, PlaceholderSign> locationLookup;
/**
* Gets all registered signs
*
* @return <p>All registered signs</p>
*/
public @NotNull Set<PlaceholderSign> getSigns() {
return new HashSet<>(placeholderSigns);
}
private Map<Chunk, Set<PlaceholderSign>> signsInChunk;
/**
* Gets a placeholder sign from the given location
@@ -57,8 +50,11 @@ public class PlaceholderSignHandler {
*/
public void registerSign(@NotNull PlaceholderSign sign) {
this.placeholderSigns.add(sign);
locationLookup.put(sign.location(), sign);
save();
this.locationLookup.put(sign.getLocation(), sign);
Chunk chunk = sign.getLocation().getChunk();
this.signsInChunk.putIfAbsent(chunk, new HashSet<>());
this.signsInChunk.get(chunk).add(sign);
}
/**
@@ -67,9 +63,24 @@ public class PlaceholderSignHandler {
* @param sign <p>The sign to un-register</p>
*/
public void unregisterSign(@NotNull PlaceholderSign sign) {
locationLookup.remove(sign.location());
this.locationLookup.remove(sign.getLocation());
this.placeholderSigns.remove(sign);
save();
this.signsInChunk.get(sign.getLocation().getChunk()).remove(sign);
}
/**
* Gets all placeholder signs in the given chunk
*
* @param chunk <p>The chunk to check</p>
* @return <p>All placeholder signs in the chunk</p>
*/
@NotNull
public Set<PlaceholderSign> getFromChunk(@NotNull Chunk chunk) {
if (this.signsInChunk.containsKey(chunk)) {
return this.signsInChunk.get(chunk);
} else {
return new HashSet<>();
}
}
/**
@@ -78,6 +89,7 @@ public class PlaceholderSignHandler {
public void load() {
this.placeholderSigns = new HashSet<>();
this.locationLookup = new HashMap<>();
this.signsInChunk = new HashMap<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile);
ConfigurationSection signSection = configuration.getConfigurationSection("signs");
@@ -104,9 +116,16 @@ public class PlaceholderSignHandler {
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);
String updateDelayKey = key + ".updateDelay";
int updateDelay = -1;
if (signSection.contains(updateDelayKey)) {
updateDelay = signSection.getInt(updateDelayKey, -1);
}
if (updateDelay < 1) {
updateDelay = PlaceholderSigns.getInstance().getSignUpdateDelay();
}
registerSign(new PlaceholderSign(signLocation, allPlaceholders, updateDelay));
}
}
@@ -153,7 +172,7 @@ public class PlaceholderSignHandler {
* @param sign <p>The sign to save</p>
*/
private void saveSign(@NotNull ConfigurationSection section, @NotNull PlaceholderSign sign) {
Location location = sign.location();
Location location = sign.getLocation();
if (location.getWorld() == null) {
return;
}
@@ -163,19 +182,21 @@ public class PlaceholderSignHandler {
String frontKey = key + ".placeholders.front";
String backKey = key + ".placeholders.back";
Map<Integer, String> frontPlaceholders = sign.placeholders().get(Side.FRONT);
Map<Integer, String> frontPlaceholders = sign.getPlaceholders().get(Side.FRONT);
if (frontPlaceholders != null) {
for (Map.Entry<Integer, String> entry : frontPlaceholders.entrySet()) {
section.set(frontKey + "." + entry.getKey(), entry.getValue());
}
}
Map<Integer, String> backPlaceholders = sign.placeholders().get(Side.BACK);
Map<Integer, String> backPlaceholders = sign.getPlaceholders().get(Side.BACK);
if (backPlaceholders != null) {
for (Map.Entry<Integer, String> entry : backPlaceholders.entrySet()) {
section.set(backKey + "." + entry.getKey(), entry.getValue());
}
}
section.set(key + ".updateDelay", sign.getUpdateDelay());
}
}

View File

@@ -0,0 +1,77 @@
package net.knarcraft.placeholdersigns.handler;
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
import net.knarcraft.placeholdersigns.container.QueuedPlaceholderSign;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.PriorityQueue;
/**
* A handler for dealing with the placeholder sign update queue
*/
public class PlaceholderSignUpdateQueueHandler {
private final PriorityQueue<QueuedPlaceholderSign> signUpdateQueue;
/**
* Instantiates a new placeholder sign update queue handler
*/
public PlaceholderSignUpdateQueueHandler() {
this.signUpdateQueue = new PriorityQueue<>();
}
/**
* Polls the queue for any placeholder signs due for update
*
* <p>No placeholder sign will be returned unless they are due to be updated.</p>
*
* @return <p>The next queued placeholder sign, or null if no such placeholder sign exists</p>
*/
@Nullable
public PlaceholderSign pollQueue() {
QueuedPlaceholderSign nextSign = signUpdateQueue.peek();
if (nextSign == null) {
return null;
}
long currentTime = System.currentTimeMillis();
if (nextSign.updateTimestamp() < currentTime) {
nextSign = signUpdateQueue.poll();
if (nextSign != null) {
return nextSign.placeholderSign();
}
}
return null;
}
/**
* Peeks at the next item in the queue
*
* @return <p>The next item in the queue, or null if empty</p>
*/
@Nullable
public QueuedPlaceholderSign peekQueue() {
return signUpdateQueue.peek();
}
/**
* Adds the specified queued sign to the queue
*
* @param queuedSign <p>The queued sign to queue</p>
*/
public void queueSign(@NotNull QueuedPlaceholderSign queuedSign) {
this.signUpdateQueue.add(queuedSign);
}
/**
* '
* Removes the specified placeholder sign from the queue
*
* @param placeholderSign <p>The placeholder sign to remove</p>
*/
public void unQueueSign(@NotNull PlaceholderSign placeholderSign) {
this.signUpdateQueue.removeIf((item) -> item.placeholderSign().equals(placeholderSign));
}
}

View File

@@ -0,0 +1,38 @@
package net.knarcraft.placeholdersigns.listener;
import net.knarcraft.placeholdersigns.PlaceholderSigns;
import net.knarcraft.placeholdersigns.container.PlaceholderSign;
import net.knarcraft.placeholdersigns.container.QueuedPlaceholderSign;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* A listener for the loading and unloading of chunks with placeholder signs
*/
public class ChunkListener implements Listener {
@EventHandler
public void onChunkLoad(@NotNull ChunkLoadEvent event) {
PlaceholderSigns instance = PlaceholderSigns.getInstance();
Set<PlaceholderSign> signsAtChunk = instance.getSignHandler().getFromChunk(event.getChunk());
long queueTime = System.currentTimeMillis();
for (PlaceholderSign sign : signsAtChunk) {
instance.getUpdateQueueHandler().queueSign(new QueuedPlaceholderSign(sign, queueTime++));
}
}
@EventHandler
public void onChunkUnload(@NotNull ChunkUnloadEvent event) {
PlaceholderSigns instance = PlaceholderSigns.getInstance();
Set<PlaceholderSign> signsAtChunk = instance.getSignHandler().getFromChunk(event.getChunk());
for (PlaceholderSign sign : signsAtChunk) {
instance.getUpdateQueueHandler().unQueueSign(sign);
}
}
}

View File

@@ -27,6 +27,7 @@ public class SignBreakListener implements Listener {
PlaceholderSign sign = signHandler.getFromLocation(block.getLocation());
if (sign != null) {
signHandler.unregisterSign(sign);
signHandler.save();
}
}

View File

@@ -133,7 +133,7 @@ public class SignClickListener implements Listener {
String text = signTextCopyRequest.sign().getSide(signTextCopyRequest.side()).getLine(sourceLine);
if (sourcePlaceholderSign != null) {
Map<Side, Map<Integer, String>> placeholders = sourcePlaceholderSign.placeholders();
Map<Side, Map<Integer, String>> placeholders = sourcePlaceholderSign.getPlaceholders();
if (placeholders.containsKey(sourceSide) && placeholders.get(sourceSide).containsKey(sourceLine)) {
text = placeholders.get(sourceSide).get(sourceLine);
}
@@ -162,12 +162,12 @@ public class SignClickListener implements Listener {
// Remove old placeholders from the sign side
Map<Integer, String> oldPlaceholders = null;
if (targetPlaceholderSign != null) {
oldPlaceholders = targetPlaceholderSign.placeholders().remove(clickedSide);
oldPlaceholders = targetPlaceholderSign.getPlaceholders().remove(clickedSide);
}
if (pasteSignSide(sourceSide, clickedSide, sourceSign, targetSign,
sourcePlaceholderSign, player) && targetPlaceholderSign != null) {
// Restore the old placeholders if the sign change didn't finish
targetPlaceholderSign.placeholders().put(clickedSide, oldPlaceholders);
targetPlaceholderSign.getPlaceholders().put(clickedSide, oldPlaceholders);
}
// Save any placeholder changes
@@ -307,7 +307,7 @@ public class SignClickListener implements Listener {
@NotNull Player player) {
String[] sideLines = signSide.getLines();
if (placeholderSign != null) {
Map<Side, Map<Integer, String>> placeholders = placeholderSign.placeholders();
Map<Side, Map<Integer, String>> placeholders = placeholderSign.getPlaceholders();
loadPlaceholders(sourceSide, sideLines, placeholders);
}
@@ -385,7 +385,7 @@ public class SignClickListener implements Listener {
String oldPlaceholder = null;
if (targetPlaceholderSign != null) {
// Remove the old placeholder
oldPlaceholder = targetPlaceholderSign.placeholders().get(targetSide).remove(destinationLine);
oldPlaceholder = targetPlaceholderSign.getPlaceholders().get(targetSide).remove(destinationLine);
}
lines[destinationLine] = newText;
@@ -396,7 +396,7 @@ public class SignClickListener implements Listener {
if (changeEvent.isCancelled()) {
if (targetPlaceholderSign != null) {
// Restore the old placeholder if the action didn't complete
targetPlaceholderSign.placeholders().get(targetSide).put(destinationLine, oldPlaceholder);
targetPlaceholderSign.getPlaceholders().get(targetSide).put(destinationLine, oldPlaceholder);
}
PlaceholderSigns.getInstance().getStringFormatter().displayErrorMessage(player,
PlaceholderSignMessage.ERROR_CANCELLED_BY_PROTECTION);

View File

@@ -61,11 +61,12 @@ public class SignTextListener implements Listener {
placeholderSide.put(event.getSide(), placeholders);
// Register a new placeholder sign
PlaceholderSign placeholderSign = new PlaceholderSign(event.getBlock().getLocation(), placeholderSide);
PlaceholderSign placeholderSign = new PlaceholderSign(event.getBlock().getLocation(), placeholderSide, null);
signHandler.registerSign(placeholderSign);
signHandler.save();
} else if (!placeholders.isEmpty()) {
// Overwrite the placeholders of the existing placeholder sign
Map<Integer, String> existing = existingSign.placeholders().computeIfAbsent(event.getSide(), k -> new HashMap<>());
Map<Integer, String> existing = existingSign.getPlaceholders().computeIfAbsent(event.getSide(), k -> new HashMap<>());
existing.putAll(placeholders);
signHandler.save();
}

View File

@@ -3,8 +3,11 @@ 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;
@@ -31,40 +34,67 @@ public class SignUpdate implements Runnable {
@Override
public void run() {
for (PlaceholderSign placeholderSign : signHandler.getSigns()) {
// Ignore signs away from players
Location location = placeholderSign.location();
if (!location.getChunk().isLoaded()) {
continue;
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;
}
// 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);
Map<Side, Map<Integer, String>> placeholders = placeholderSign.placeholders();
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();
}
updatePlaceholderSign(placeholderSign, currentTime);
}
}
/**
* Updates the contents of a single placeholder sign
*
* @param placeholderSign <p>The placeholder sign to update</p>
* @param currentTime <p>The current time, used for re-queuing the sign</p>
*/
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<Side, Map<Integer, String>> 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
*

View File

@@ -13,6 +13,7 @@ public final class TabCompleteHelper {
private static final List<String> lineNumbers;
private static final List<String> signSides;
private static final List<String> updateDelays;
static {
lineNumbers = new ArrayList<>();
@@ -24,12 +25,24 @@ public final class TabCompleteHelper {
for (Side side : Side.values()) {
signSides.add(side.name());
}
updateDelays = List.of("null", "1", "5", "10", "20", "40", "60", "80", "100");
}
private TabCompleteHelper() {
}
/**
* Gets possible sign update delays
*
* @return <p>Possible sign update delays</p>
*/
@NotNull
public static List<String> getDelays() {
return new ArrayList<>(updateDelays);
}
/**
* Gets possible sign line numbers
*