2023-04-05 22:02:29 +02:00

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;
}
}