182 lines
6.1 KiB
Java
182 lines
6.1 KiB
Java
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<Player, LineChangeRequest> changeRequests;
|
|
|
|
/**
|
|
* Gets an instance of this plugin
|
|
*
|
|
* @return <p>A plugin instance</p>
|
|
*/
|
|
public static @NotNull PlaceholderSigns getInstance() {
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Gets this instance's placeholder sign handler
|
|
*
|
|
* @return <p>The sign handler</p>
|
|
*/
|
|
public @NotNull PlaceholderSignHandler getSignHandler() {
|
|
return this.signHandler;
|
|
}
|
|
|
|
/**
|
|
* Registers a sign change request
|
|
*
|
|
* <p>A sign change request is basically the result of running the editSign command, which must be stored until the
|
|
* player clicks a sign.</p>
|
|
*
|
|
* @param request <p>The sign change request to register</p>
|
|
*/
|
|
public void addChangeRequest(@NotNull LineChangeRequest request) {
|
|
changeRequests.put(request.player(), request);
|
|
}
|
|
|
|
/**
|
|
* Gets a sign change request
|
|
*
|
|
* @param player <p>The player to get the request for</p>
|
|
* @return <p>The sign change request, or null if not found</p>
|
|
*/
|
|
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<Integer, String> 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 <p>The string to search for color codes</p>
|
|
* @return <p>The message with color codes translated</p>
|
|
*/
|
|
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;
|
|
}
|
|
|
|
}
|