From a77c297e580d39a48a691c5884347893167a8006 Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Mon, 10 Jan 2022 18:37:11 +0100 Subject: [PATCH] Adds code for loading and saving sign data --- .../permissionsigns/PermissionSigns.java | 18 +++ .../permissionsigns/SignManager.java | 136 ++++++++++++++++++ .../command/CancelCommand.java | 13 +- .../command/CreateCommand.java | 29 +++- .../command/PermissionSignsCommand.java | 10 +- .../command/ReloadCommand.java | 21 ++- .../container/PermissionSign.java | 11 +- .../formatting/StringFormatter.java | 3 +- .../formatting/TranslatableMessage.java | 57 +++++++- .../formatting/Translator.java | 19 ++- .../permissionsigns/utility/FileHelper.java | 27 ++++ src/main/resources/strings.yml | 22 +-- 12 files changed, 330 insertions(+), 36 deletions(-) create mode 100644 src/main/java/net/knarcraft/permissionsigns/SignManager.java create mode 100644 src/main/java/net/knarcraft/permissionsigns/utility/FileHelper.java diff --git a/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java b/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java index 2acffde..4dbdff0 100644 --- a/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java +++ b/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java @@ -22,6 +22,24 @@ public final class PermissionSigns extends JavaPlugin { private static final Queue signCreationRequests = new PriorityQueue<>(); private static String pluginVersion; + private static PermissionSigns instance; + + /** + * Instantiates the permission signs class + */ + public PermissionSigns() { + super(); + instance = this; + } + + /** + * Gets an instance of this plugin + * + * @return

An instance of this plugin

+ */ + public static PermissionSigns getInstance() { + return instance; + } /** * Gets the version of this plugin diff --git a/src/main/java/net/knarcraft/permissionsigns/SignManager.java b/src/main/java/net/knarcraft/permissionsigns/SignManager.java new file mode 100644 index 0000000..edc9a7e --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/SignManager.java @@ -0,0 +1,136 @@ +package net.knarcraft.permissionsigns; + +import net.knarcraft.permissionsigns.container.PermissionSign; +import org.bukkit.Bukkit; +import org.bukkit.Location; +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.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Level; + +/** + * A manager for keeping track of known signs + */ +public class SignManager { + + private static Map managedSigns = new HashMap<>(); + private static final File signsFile = new File(PermissionSigns.getInstance().getDataFolder(), "signs.yml"); + + /** + * Gets a copy of all managed signs + * + * @return

All managed signs

+ */ + public static Map getSigns() { + return new HashMap<>(managedSigns); + } + + /** + * Adds a sign + * + * @param sign

The sign to add

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

The sign to remove

+ */ + public static void removeSign(PermissionSign sign) { + managedSigns.remove(sign.getSignLocation()); + } + + /** + * 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) { + 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()); + } + } + } + + /** + * 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(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"); + int cost = signSection.getInt(key + ".cost"); + + PermissionSign loadedSign = new PermissionSign(signLocation, signName, permissionStrings, duration, cost); + managedSigns.put(signLocation, loadedSign); + } + +} diff --git a/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java index 6a34da8..1296635 100644 --- a/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java +++ b/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java @@ -1,6 +1,9 @@ package net.knarcraft.permissionsigns.command; import net.knarcraft.permissionsigns.PermissionSigns; +import net.knarcraft.permissionsigns.formatting.StringFormatter; +import net.knarcraft.permissionsigns.formatting.TranslatableMessage; +import net.knarcraft.permissionsigns.formatting.Translator; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -14,7 +17,15 @@ public class CancelCommand implements CommandExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - PermissionSigns.cancelSignCreationRequest(((Player) sender).getUniqueId()); + if (sender instanceof Player player) { + if (sender.hasPermission("permissionsigns.admin.create")) { + PermissionSigns.cancelSignCreationRequest(player.getUniqueId()); + } else { + sender.sendMessage(StringFormatter.formatErrorMessage(Translator.getTranslatedMessage(TranslatableMessage.COMMAND_PERMISSION_DENIED))); + } + } else { + sender.sendMessage(StringFormatter.formatErrorMessage(Translator.getTranslatedMessage(TranslatableMessage.COMMAND_PLAYER_ONLY))); + } return true; } diff --git a/src/main/java/net/knarcraft/permissionsigns/command/CreateCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/CreateCommand.java index e7988b8..c0b374b 100644 --- a/src/main/java/net/knarcraft/permissionsigns/command/CreateCommand.java +++ b/src/main/java/net/knarcraft/permissionsigns/command/CreateCommand.java @@ -2,6 +2,7 @@ package net.knarcraft.permissionsigns.command; import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.container.PermissionSign; +import net.knarcraft.permissionsigns.formatting.StringFormatter; import net.knarcraft.permissionsigns.formatting.TranslatableMessage; import net.knarcraft.permissionsigns.formatting.Translator; import org.bukkit.command.Command; @@ -25,11 +26,31 @@ public class CreateCommand implements CommandExecutor { sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.COMMAND_PLAYER_ONLY)); return false; } + if (!sender.hasPermission("permissionsigns.admin.create")) { + sender.sendMessage(StringFormatter.formatErrorMessage(Translator.getTranslatedMessage(TranslatableMessage.COMMAND_PERMISSION_DENIED))); + return false; + } if (args.length < 2) { sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.MISSING_CREATION_INFO)); return false; } + PermissionSign newSign = parseSign(sender, args); + if (newSign == null) { + return false; + } + PermissionSigns.addSignCreationRequest((Player) sender, newSign); + return true; + } + + /** + * Parses the permission sign given in user input + * + * @param sender

The sender that initiated the command

+ * @param args

The given command arguments

+ * @return

The parsed sign, or null if it could not be parsed

+ */ + private PermissionSign parseSign(@NotNull CommandSender sender, @NotNull String[] args) { String name = args[0]; String[] permissions = args[1].split(","); int cost; @@ -38,18 +59,16 @@ public class CreateCommand implements CommandExecutor { cost = Integer.parseInt(args[2]); } catch (NumberFormatException exception) { sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.COST_INVALID_NUMBER)); - return false; + return null; } try { duration = Integer.parseInt(args[3]); } catch (NumberFormatException exception) { sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.DURATION_INVALID_NUMBER)); - return false; + return null; } - PermissionSign newSign = new PermissionSign(name, List.of(permissions), cost, duration); - PermissionSigns.addSignCreationRequest((Player) sender, newSign); - return true; + return new PermissionSign(name, List.of(permissions), cost, duration); } } diff --git a/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsCommand.java index 040ad33..9c75352 100644 --- a/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsCommand.java +++ b/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsCommand.java @@ -1,5 +1,6 @@ package net.knarcraft.permissionsigns.command; +import org.apache.commons.lang.ArrayUtils; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -14,11 +15,14 @@ public class PermissionSignsCommand implements CommandExecutor { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (args.length > 0) { if (args[0].equalsIgnoreCase("create")) { - + String[] subArgs = (String[]) ArrayUtils.remove(args, 0); + return new CreateCommand().onCommand(sender, command, label, subArgs); } else if (args[0].equalsIgnoreCase("cancel")) { - + return new CancelCommand().onCommand(sender, command, label, args); } else if (args[0].equalsIgnoreCase("about")) { - + return new AboutCommand().onCommand(sender, command, label, args); + } else if (args[0].equalsIgnoreCase("reload")) { + return new ReloadCommand().onCommand(sender, command, label, args); } } return false; diff --git a/src/main/java/net/knarcraft/permissionsigns/command/ReloadCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/ReloadCommand.java index adf8506..0724ed0 100644 --- a/src/main/java/net/knarcraft/permissionsigns/command/ReloadCommand.java +++ b/src/main/java/net/knarcraft/permissionsigns/command/ReloadCommand.java @@ -1,4 +1,23 @@ package net.knarcraft.permissionsigns.command; -public class ReloadCommand { +import net.knarcraft.permissionsigns.formatting.StringFormatter; +import net.knarcraft.permissionsigns.formatting.TranslatableMessage; +import net.knarcraft.permissionsigns.formatting.Translator; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class ReloadCommand implements CommandExecutor { + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (sender.hasPermission("permissionsigns.admin.reload")) { + //TODO: Perform a reload from disk + } else { + sender.sendMessage(StringFormatter.formatErrorMessage(Translator.getTranslatedMessage(TranslatableMessage.COMMAND_PERMISSION_DENIED))); + } + return true; + } + } diff --git a/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java b/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java index c127683..2c39a6d 100644 --- a/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java +++ b/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java @@ -14,7 +14,7 @@ import java.util.List; public class PermissionSign { private Location signLocation; - private String name; + private final String name; private final List permissionNodes; private final int duration; private final int cost; @@ -47,6 +47,7 @@ public class PermissionSign { * @param cost

The cost of using this permission sign

*/ public PermissionSign(String name, List permissionNodes, int duration, int cost) { + this.name = name; this.permissionNodes = new ArrayList<>(permissionNodes); this.duration = Math.max(0, duration); this.cost = Math.max(0, cost); @@ -121,7 +122,7 @@ public class PermissionSign { */ public String[] getSignLines() { String[] lines = new String[4]; - lines[0] = ChatColor.RED + Translator.getTranslatedMessage(TranslatableMessage.PREFIX); + lines[0] = ChatColor.DARK_RED + Translator.getTranslatedMessage(TranslatableMessage.PREFIX); lines[1] = getName(); lines[2] = getDurationString(); lines[3] = getCostString(); @@ -147,9 +148,9 @@ public class PermissionSign { */ private String getDurationString() { if (duration == 0) { - return Translator.getTranslatedMessage(TranslatableMessage.PERMANENT); + return Translator.getTranslatedMessage(TranslatableMessage.SIGN_PERMANENT); } else { - return duration + " " + Translator.getTranslatedMessage(TranslatableMessage.TIME_UNIT); + return duration + " " + Translator.getTranslatedMessage(TranslatableMessage.SIGN_TIME_UNIT); } } @@ -160,7 +161,7 @@ public class PermissionSign { */ private String getCostString() { if (cost == 0) { - return Translator.getTranslatedMessage(TranslatableMessage.COST_FREE); + return Translator.getTranslatedMessage(TranslatableMessage.SIGN_COST_FREE); } else { //TODO: Get currency unit from Vault return cost + "$"; diff --git a/src/main/java/net/knarcraft/permissionsigns/formatting/StringFormatter.java b/src/main/java/net/knarcraft/permissionsigns/formatting/StringFormatter.java index 969a853..f9f6e48 100644 --- a/src/main/java/net/knarcraft/permissionsigns/formatting/StringFormatter.java +++ b/src/main/java/net/knarcraft/permissionsigns/formatting/StringFormatter.java @@ -34,7 +34,8 @@ public class StringFormatter { * @return

The formatted message

*/ private static String formatMessage(String message) { - return Translator.getTranslatedMessage(TranslatableMessage.PREFIX) + ChatColor.GRAY + message; + return ChatColor.translateAlternateColorCodes('&', + Translator.getTranslatedMessage(TranslatableMessage.PREFIX)) + ChatColor.RESET + message; } } diff --git a/src/main/java/net/knarcraft/permissionsigns/formatting/TranslatableMessage.java b/src/main/java/net/knarcraft/permissionsigns/formatting/TranslatableMessage.java index dc8487c..0a1983f 100644 --- a/src/main/java/net/knarcraft/permissionsigns/formatting/TranslatableMessage.java +++ b/src/main/java/net/knarcraft/permissionsigns/formatting/TranslatableMessage.java @@ -5,15 +5,64 @@ package net.knarcraft.permissionsigns.formatting; */ public enum TranslatableMessage { + /** + * The prefix to display in messages + */ PREFIX, - MISSING_CREATION_INFO, - TIME_UNIT, - COST_FREE, - PERMANENT, + + /** + * The prefix to display on signs + */ + SIGN_PREFIX, + + /** + * The text to display as a permission sign's duration time unit + */ + SIGN_TIME_UNIT, + + /** + * The text to display on a permission sign that is entirely free + */ + SIGN_COST_FREE, + + /** + * The text to display on a permissions sign whose permissions never expire + */ + SIGN_PERMANENT, + + /** + * The error message to display if the given cost is not a valid number + */ COST_INVALID_NUMBER, + + /** + * The error message to display if the given duration is not a valid number + */ DURATION_INVALID_NUMBER, + + /** + * The error message to display if a player-only command is executed from the console + */ COMMAND_PLAYER_ONLY, + + /** + * The error message to display if a player attempts to break a permission sign without the necessary permissions + */ PERMISSION_SIGN_DESTROY_DENY, + + /** + * The error message to display if the user has not provided necessary information to create a permission sign + */ + MISSING_CREATION_INFO, + + /** + * The error message to be displayed when a player is denied from executing a command + */ + COMMAND_PERMISSION_DENIED, + + /** + * The message to be displayed when a player successfully destroys a permissions sign + */ PERMISSION_SIGN_REMOVED } diff --git a/src/main/java/net/knarcraft/permissionsigns/formatting/Translator.java b/src/main/java/net/knarcraft/permissionsigns/formatting/Translator.java index 2c1c84b..4724b4c 100644 --- a/src/main/java/net/knarcraft/permissionsigns/formatting/Translator.java +++ b/src/main/java/net/knarcraft/permissionsigns/formatting/Translator.java @@ -1,12 +1,14 @@ package net.knarcraft.permissionsigns.formatting; +import net.knarcraft.permissionsigns.PermissionSigns; +import net.knarcraft.permissionsigns.utility.FileHelper; import org.bukkit.configuration.file.YamlConfiguration; import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Map; +import java.util.logging.Level; /** * A tool to get strings translated to the correct language @@ -31,6 +33,9 @@ public class Translator { * @return

The translated message

*/ public static String getTranslatedMessage(TranslatableMessage translatableMessage) { + if (translatedMessages == null) { + return "Translated strings not loaded"; + } if (translatedMessages.containsKey(translatableMessage)) { return translatedMessages.get(translatableMessage); } else if (backupTranslatedMessages.containsKey(translatableMessage)) { @@ -48,11 +53,13 @@ public class Translator { */ public static Map loadTranslatedMessages(String language) { Map translatedMessages = new HashMap<>(); - InputStream inputStream = Translator.class.getResourceAsStream("/strings.yml"); - if (inputStream == null) { - throw new IllegalArgumentException("Unable to load strings"); + BufferedReader reader; + try { + reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml"); + } catch (FileNotFoundException e) { + PermissionSigns.getInstance().getLogger().log(Level.SEVERE, "Unable to load translated messages"); + return null; } - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader); for (TranslatableMessage message : TranslatableMessage.values()) { diff --git a/src/main/java/net/knarcraft/permissionsigns/utility/FileHelper.java b/src/main/java/net/knarcraft/permissionsigns/utility/FileHelper.java new file mode 100644 index 0000000..1eb5fb4 --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/utility/FileHelper.java @@ -0,0 +1,27 @@ +package net.knarcraft.permissionsigns.utility; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * A helper class for dealing with files + */ +public class FileHelper { + + /** + * Gets a buffered reader for + * + * @return

A buffered read for reading the file

+ * @throws FileNotFoundException

If unable to get an input stream for the given file

+ */ + public static BufferedReader getBufferedReaderForInternalFile(String file) throws FileNotFoundException { + InputStream inputStream = FileHelper.class.getResourceAsStream(file); + if (inputStream == null) { + throw new FileNotFoundException("Unable to read the given file"); + } + return new BufferedReader(new InputStreamReader(inputStream)); + } + +} diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index b40e53a..b3606c9 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -1,11 +1,13 @@ en: - PREFIX: "[PermSign]" - MISSING_CREATION_INFO: "You must specify a sign name and a comma-separated list of permissions to create a permission sign" - TIME_UNIT: "seconds" - PERMANENT: "Permanent" - COST_FREE: "Free" - COST_INVALID_NUMBER: "The given cost is not a valid number" - DURATION_INVALID_NUMBER: "The given duration is not a valid number" - COMMAND_PLAYER_ONLY: "This command is only available to players" - PERMISSION_SIGN_DESTROY_DENY: "You do not have permissions to delete a permissions sign" - PERMISSION_SIGN_REMOVED: "Permissions sign removed" \ No newline at end of file + PREFIX: "[PermissionSigns]" + SIGN_PREFIX: "&4[PermSign]" + MISSING_CREATION_INFO: "&7You must specify a sign name and a comma-separated list of permissions to create a permission sign" + SIGN_TIME_UNIT: "seconds" + SIGN_PERMANENT: "Permanent" + SIGN_COST_FREE: "Free" + COST_INVALID_NUMBER: "&7The given cost is not a valid number" + DURATION_INVALID_NUMBER: "&7The given duration is not a valid number" + COMMAND_PLAYER_ONLY: "&7This command is only available to players" + PERMISSION_SIGN_DESTROY_DENY: "&7You do not have permissions to delete a permissions sign" + PERMISSION_SIGN_REMOVED: "&7Permissions sign removed" + COMMAND_PERMISSION_DENIED: "&7You do not have necessary permissions to perform this command" \ No newline at end of file