package net.knarcraft.permissionsigns.manager; import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.container.PermissionSign; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.Sign; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.logging.Level; /** * A manager for keeping track of known signs */ public final class SignManager { private static Map managedSigns = new HashMap<>(); private static final File signsFile = new File(PermissionSigns.getInstance().getDataFolder(), "data.yml"); private SignManager() { } /** * Gets the permission sign at the given location * * @param signLocation

The location of the permission sign to get

* @return

The permission sign at the given location, or null if no such sign exists

*/ public static PermissionSign getSign(Location signLocation) { return managedSigns.get(signLocation); } /** * Adds a sign * * @param sign

The sign to add

*/ public static void addSign(PermissionSign sign) { managedSigns.put(sign.getSignLocation(), sign); save(); } /** * Removes a sign * * @param location

The location of the sign to remove

*/ public static void removeSign(Location location) { managedSigns.remove(location); save(); } /** * Saves all signs to the signs file * * @throws IOException

If unable to save to the signs file

*/ public static void saveSigns() throws IOException { YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile); ConfigurationSection signSection = configuration.createSection("signs"); for (Location signLocation : managedSigns.keySet()) { String locationString = Objects.requireNonNull(signLocation.getWorld()).getUID() + "," + signLocation.getBlockX() + "," + signLocation.getBlockY() + "," + signLocation.getBlockZ(); PermissionSign sign = managedSigns.get(signLocation); signSection.set(locationString + ".name", sign.getName()); signSection.set(locationString + ".permissions", sign.getPermissionNodes()); signSection.set(locationString + ".duration", sign.getDuration()); signSection.set(locationString + ".cost", sign.getCost()); } configuration.save(signsFile); } /** * Loads all saved signs from disk */ public static void loadSigns() { YamlConfiguration configuration = YamlConfiguration.loadConfiguration(signsFile); ConfigurationSection signSection = configuration.getConfigurationSection("signs"); managedSigns = new HashMap<>(); if (signSection == null) { PermissionSigns.getInstance().getLogger().log(Level.WARNING, "Signs section not found in data.yml"); return; } for (String key : signSection.getKeys(false)) { try { loadSign(signSection, key); } catch (InvalidConfigurationException e) { PermissionSigns.getInstance().getLogger().log(Level.SEVERE, "Unable to load sign " + key + ": " + e.getMessage()); } } //Re-draw all signs in a separate thread redrawSigns(); } /** * Re-draws all loaded signs in case something changed */ private static void redrawSigns() { Bukkit.getScheduler().scheduleSyncDelayedTask(PermissionSigns.getInstance(), () -> { List invalidPermissionSigns = new ArrayList<>(); for (Location key : managedSigns.keySet()) { PermissionSign permissionSign = managedSigns.get(key); Block signBlock = key.getBlock(); BlockState state = signBlock.getState(); if (!(state instanceof Sign sign)) { if (PermissionSigns.removePermissionSignIfMissing()) { invalidPermissionSigns.add(permissionSign.getSignLocation()); } continue; } String[] newLines = permissionSign.getSignLines(); if (Arrays.equals(sign.getLines(), newLines)) { continue; } for (int i = 0; i < 4; i++) { sign.setLine(i, newLines[i]); } sign.update(); } for (Location signLocation : invalidPermissionSigns) { SignManager.removeSign(signLocation); } }); } /** * Tries to save signs and handles any errors */ private static void save() { try { saveSigns(); } catch (IOException e) { PermissionSigns.getInstance().getLogger().log(Level.SEVERE, "Unable to save signs: " + e.getMessage()); } } /** * Loads a sign from the save file * * @param signSection

The configuration section containing signs

* @param key

The sign key which is also the sign's location

* @throws InvalidConfigurationException

If unable to load the sign

*/ private static void loadSign(ConfigurationSection signSection, String key) throws InvalidConfigurationException { String[] locationParts = key.split(","); Location signLocation; try { signLocation = new Location(Bukkit.getWorld(UUID.fromString(locationParts[0])), Double.parseDouble(locationParts[1]), Double.parseDouble(locationParts[2]), Double.parseDouble(locationParts[3])); } catch (NumberFormatException exception) { throw new InvalidConfigurationException("Invalid sign coordinates"); } String signName = signSection.getString(key + ".name"); if (signName == null) { throw new IllegalArgumentException("Name missing from sign data"); } List permissionStrings = new ArrayList<>(); List permissions = signSection.getList(key + ".permissions"); if (permissions == null) { throw new IllegalArgumentException("Permission list missing from sign data"); } permissions.forEach((item) -> { if (item instanceof String) { permissionStrings.add((String) item); } }); int duration = signSection.getInt(key + ".duration"); double cost = signSection.getDouble(key + ".cost"); PermissionSign loadedSign = new PermissionSign(signLocation, signName, permissionStrings, duration, cost); managedSigns.put(signLocation, loadedSign); } }