diff --git a/README.md b/README.md new file mode 100644 index 0000000..a136b73 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Permission Signs + +This is a plugin based on the permission signs plugin created by _ForgeUser7294733. As the previous plugin does not +offer source code and has a restrictive license, this plugin is written from scratch, but trying to imitate the original +plugin's behavior. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 869314e..62e094d 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ A plugin for selling permissions using signs - 16 + 17 UTF-8 git.knarcraft.net @@ -69,8 +69,14 @@ org.spigotmc spigot-api - 1.17.1-R0.1-SNAPSHOT + 1.18.1-R0.1-SNAPSHOT provided + + org.jetbrains + annotations + RELEASE + compile + diff --git a/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java b/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java index 130bae8..2acffde 100644 --- a/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java +++ b/src/main/java/net/knarcraft/permissionsigns/PermissionSigns.java @@ -1,9 +1,14 @@ package net.knarcraft.permissionsigns; +import net.knarcraft.permissionsigns.command.PermissionSignsCommand; +import net.knarcraft.permissionsigns.command.PermissionSignsTabCompleter; +import net.knarcraft.permissionsigns.container.PermissionSign; import net.knarcraft.permissionsigns.container.SignCreationRequest; import net.knarcraft.permissionsigns.thread.SignCreationRequestTimeoutThread; import org.bukkit.Bukkit; +import org.bukkit.command.PluginCommand; import org.bukkit.entity.Player; +import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; @@ -14,12 +19,32 @@ import java.util.UUID; import java.util.stream.Stream; public final class PermissionSigns extends JavaPlugin { - - private static Queue signCreationRequests = new PriorityQueue<>(); + + private static final Queue signCreationRequests = new PriorityQueue<>(); + private static String pluginVersion; + + /** + * Gets the version of this plugin + * + * @return

This plugin's version

+ */ + public static String getPluginVersion() { + return pluginVersion; + } + + /** + * Adds a new sign creation request + * + * @param player

The player that initiated the sign creation

+ * @param sign

The sign the player is about to create

+ */ + public static void addSignCreationRequest(Player player, PermissionSign sign) { + signCreationRequests.add(new SignCreationRequest(sign, player, System.currentTimeMillis())); + } /** * Gets the sign creation request for the player with the given UUID - * + * * @param uuid

The UUID to get a sign creation request for

* @return

A sign creation request, or null if the UUID is not found

*/ @@ -34,10 +59,25 @@ public final class PermissionSigns extends JavaPlugin { } } + /** + * Cancels the sign creation request triggered by the user + * + * @param uuid

The UUID of the player to cancel the request for

+ */ + public static void cancelSignCreationRequest(UUID uuid) { + Stream matchingRequests = signCreationRequests.stream().filter( + (item) -> item.getPlayer().getUniqueId().equals(uuid)); + List requestList = matchingRequests.toList(); + signCreationRequests.remove(requestList.get(0)); + } + @Override public void onEnable() { + PluginDescriptionFile pluginDescriptionFile = this.getDescription(); + pluginVersion = pluginDescriptionFile.getVersion(); + // Plugin startup logic - + //TODO: Add commands create, add and remove // /ps create, /ps add, and /ps remove // create initiates the creation, and add adds properties @@ -53,7 +93,7 @@ public final class PermissionSigns extends JavaPlugin { // /ps cancel to cancel the sing creation // Break the sign to remove it, check for permission first // The name thing is probably useless, as the sign's location works as its id - + //TODO: Display and register the permission-sign // Start with [PermSign] in red // Next line is the permission node. Last child, upper-cased @@ -61,23 +101,36 @@ public final class PermissionSigns extends JavaPlugin { // Last line is the cost, including the unit // Need to store any temporary permissions in a list/queue and have a thread which searches for expired // permissions to de-register them - + //Not persistent, but might work as things shouldn't persist anyway //player.addAttachment(this, "essentials.fly", true, seconds * 20); //Vault probably has some API to add permissions - - + + //TODO: Start sign creation when the create command is used and save the data until an empty sign is right-clicked - + //TODO: Check for existence of old permission signs when clicked and register them as new permission signs. If // it has the permissionSigns header and a name matching contents in signdata.yml, add it. + registerCommands(); BukkitScheduler scheduler = Bukkit.getScheduler(); scheduler.runTaskTimer(this, new SignCreationRequestTimeoutThread(signCreationRequests), 0L, 100L); } + /** + * Registers a command for this plugin + */ + private void registerCommands() { + PluginCommand stargateCommand = this.getCommand("permissionsigns"); + if (stargateCommand != null) { + stargateCommand.setExecutor(new PermissionSignsCommand()); + stargateCommand.setTabCompleter(new PermissionSignsTabCompleter()); + } + } + @Override public void onDisable() { // Plugin shutdown logic } + } diff --git a/src/main/java/net/knarcraft/permissionsigns/command/AboutCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/AboutCommand.java new file mode 100644 index 0000000..d418364 --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/command/AboutCommand.java @@ -0,0 +1,24 @@ +package net.knarcraft.permissionsigns.command; + +import net.knarcraft.permissionsigns.PermissionSigns; +import net.knarcraft.permissionsigns.formatting.StringFormatter; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +/** + * A command for getting information about the plugin + */ +public class AboutCommand implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + sender.sendMessage(StringFormatter.formatInfoMessage("Permission Signs plugin created by " + ChatColor.GOLD + + "EpicKnarvik97")); + sender.sendMessage(StringFormatter.formatInfoMessage("Plugin version: " + PermissionSigns.getPluginVersion())); + return true; + } + +} diff --git a/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java index 5c3b2ea..6a34da8 100644 --- a/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java +++ b/src/main/java/net/knarcraft/permissionsigns/command/CancelCommand.java @@ -1,14 +1,21 @@ package net.knarcraft.permissionsigns.command; +import net.knarcraft.permissionsigns.PermissionSigns; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +/** + * The command used to cancel a sign creation request + */ public class CancelCommand implements CommandExecutor { - + @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - return false; + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + PermissionSigns.cancelSignCreationRequest(((Player) sender).getUniqueId()); + 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 54bb9dc..e7988b8 100644 --- a/src/main/java/net/knarcraft/permissionsigns/command/CreateCommand.java +++ b/src/main/java/net/knarcraft/permissionsigns/command/CreateCommand.java @@ -1,17 +1,55 @@ package net.knarcraft.permissionsigns.command; +import net.knarcraft.permissionsigns.PermissionSigns; +import net.knarcraft.permissionsigns.container.PermissionSign; +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.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import java.util.List; + +/** + * The command used to create a new permission sign + */ public class CreateCommand implements CommandExecutor { - + @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { // /ps create to create a new permission-sign //Name and permission(s) required, but duration and cost optional - - return false; + if (!(sender instanceof Player)) { + sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.COMMAND_PLAYER_ONLY)); + return false; + } + if (args.length < 2) { + sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.MISSING_CREATION_INFO)); + return false; + } + + String name = args[0]; + String[] permissions = args[1].split(","); + int cost; + int duration; + try { + cost = Integer.parseInt(args[2]); + } catch (NumberFormatException exception) { + sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.COST_INVALID_NUMBER)); + return false; + } + try { + duration = Integer.parseInt(args[3]); + } catch (NumberFormatException exception) { + sender.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.DURATION_INVALID_NUMBER)); + return false; + } + + PermissionSign newSign = new PermissionSign(name, List.of(permissions), cost, duration); + PermissionSigns.addSignCreationRequest((Player) sender, newSign); + return true; } - + } diff --git a/src/main/java/net/knarcraft/permissionsigns/command/CreateTabCompleter.java b/src/main/java/net/knarcraft/permissionsigns/command/CreateTabCompleter.java index 705846a..e8c8081 100644 --- a/src/main/java/net/knarcraft/permissionsigns/command/CreateTabCompleter.java +++ b/src/main/java/net/knarcraft/permissionsigns/command/CreateTabCompleter.java @@ -3,14 +3,18 @@ package net.knarcraft.permissionsigns.command; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; import java.util.List; +/** + * The tab completer for the create command + */ public class CreateTabCompleter implements TabCompleter { - + @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { return null; } - + } diff --git a/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsCommand.java new file mode 100644 index 0000000..040ad33 --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsCommand.java @@ -0,0 +1,27 @@ +package net.knarcraft.permissionsigns.command; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +/** + * The main command for this plugin + */ +public class PermissionSignsCommand implements CommandExecutor { + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length > 0) { + if (args[0].equalsIgnoreCase("create")) { + + } else if (args[0].equalsIgnoreCase("cancel")) { + + } else if (args[0].equalsIgnoreCase("about")) { + + } + } + return false; + } + +} diff --git a/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsTabCompleter.java b/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsTabCompleter.java new file mode 100644 index 0000000..1fe7be2 --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/command/PermissionSignsTabCompleter.java @@ -0,0 +1,56 @@ +package net.knarcraft.permissionsigns.command; + +import org.apache.commons.lang.ArrayUtils; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * The tab completer for this plugin's main command + */ +public class PermissionSignsTabCompleter implements TabCompleter { + + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + List commands = getAvailableCommands(sender); + List matchingCommands = new ArrayList<>(); + for (String availableCommand : commands) { + if (availableCommand.startsWith(args[0])) { + matchingCommands.add(availableCommand); + } + } + return matchingCommands; + } else if (args.length > 1 && args[0].equalsIgnoreCase("create")) { + String[] subArgs = (String[]) ArrayUtils.remove(args, 0); + return new CreateTabCompleter().onTabComplete(sender, command, alias, subArgs); + } else { + return new ArrayList<>(); + } + } + + /** + * Gets the available commands + * + * @param commandSender

The command sender to get available commands for

+ * @return

The commands available to the command sender

+ */ + private List getAvailableCommands(CommandSender commandSender) { + List commands = new ArrayList<>(); + commands.add("about"); + if (!(commandSender instanceof Player player) || player.hasPermission("permissionsigns.admin.reload")) { + commands.add("reload"); + } + if (commandSender instanceof Player player && player.hasPermission("permissionsigns.admin.create")) { + commands.add("create"); + commands.add("cancel"); + } + return commands; + } + +} diff --git a/src/main/java/net/knarcraft/permissionsigns/command/ReloadCommand.java b/src/main/java/net/knarcraft/permissionsigns/command/ReloadCommand.java new file mode 100644 index 0000000..adf8506 --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/command/ReloadCommand.java @@ -0,0 +1,4 @@ +package net.knarcraft.permissionsigns.command; + +public class ReloadCommand { +} diff --git a/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java b/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java index b2f51dd..c127683 100644 --- a/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java +++ b/src/main/java/net/knarcraft/permissionsigns/container/PermissionSign.java @@ -1,6 +1,8 @@ package net.knarcraft.permissionsigns.container; -import net.knarcraft.permissionsigns.PermissionSigns; +import net.knarcraft.permissionsigns.formatting.TranslatableMessage; +import net.knarcraft.permissionsigns.formatting.Translator; +import org.bukkit.ChatColor; import org.bukkit.Location; import java.util.ArrayList; @@ -30,6 +32,8 @@ public class PermissionSign { this.signLocation = signLocation; this.name = name; this.permissionNodes = new ArrayList<>(permissionNodes); + + //Automatically fix negative values this.duration = Math.max(0, duration); this.cost = Math.max(0, cost); } @@ -37,11 +41,12 @@ public class PermissionSign { /** * Instantiates a new permission sign * + * @param name

The name to display on the permission sign

* @param permissionNodes

The permissions granted when this permission sign is used

* @param duration

The duration, in seconds, until the permission should be revoked. 0 for non-temporary

* @param cost

The cost of using this permission sign

*/ - public PermissionSign(List permissionNodes, int duration, int cost) { + public PermissionSign(String name, List permissionNodes, int duration, int cost) { this.permissionNodes = new ArrayList<>(permissionNodes); this.duration = Math.max(0, duration); this.cost = Math.max(0, cost); @@ -49,7 +54,7 @@ public class PermissionSign { /** * Sets the sign location of this permission sign - * + * * @param signLocation

>The location of this permission sign's actual sign

*/ public void setSignLocation(Location signLocation) { @@ -64,7 +69,7 @@ public class PermissionSign { * Gets the location of this permission sign * *

The location might be null until a sign has been right-clicked

- * + * * @return

The location of this permission sign

*/ public Location getSignLocation() { @@ -73,7 +78,7 @@ public class PermissionSign { /** * Gets the name of this permission sign - * + * * @return

The name of this permission sign

*/ public String getName() { @@ -108,7 +113,21 @@ public class PermissionSign { public int getCost() { return this.cost; } - + + /** + * Gets the lines used to represent this permission sign on a sign + * + * @return

The lines used to draw this permission sign

+ */ + public String[] getSignLines() { + String[] lines = new String[4]; + lines[0] = ChatColor.RED + Translator.getTranslatedMessage(TranslatableMessage.PREFIX); + lines[1] = getName(); + lines[2] = getDurationString(); + lines[3] = getCostString(); + return lines; + } + @Override public boolean equals(Object other) { if (!(other instanceof PermissionSign)) { @@ -117,8 +136,35 @@ public class PermissionSign { if (this == other) { return true; } - + return this.signLocation.equals(((PermissionSign) other).signLocation); } + /** + * Gets the string used for displaying this sign's duration + * + * @return

The string used for displaying this sign's duration

+ */ + private String getDurationString() { + if (duration == 0) { + return Translator.getTranslatedMessage(TranslatableMessage.PERMANENT); + } else { + return duration + " " + Translator.getTranslatedMessage(TranslatableMessage.TIME_UNIT); + } + } + + /** + * Gets the string used for displaying this sign's cost + * + * @return

The string used for displaying this sign's cost

+ */ + private String getCostString() { + if (cost == 0) { + return Translator.getTranslatedMessage(TranslatableMessage.COST_FREE); + } else { + //TODO: Get currency unit from Vault + return cost + "$"; + } + } + } diff --git a/src/main/java/net/knarcraft/permissionsigns/container/SignCreationRequest.java b/src/main/java/net/knarcraft/permissionsigns/container/SignCreationRequest.java index e7a8951..9cb6025 100644 --- a/src/main/java/net/knarcraft/permissionsigns/container/SignCreationRequest.java +++ b/src/main/java/net/knarcraft/permissionsigns/container/SignCreationRequest.java @@ -6,16 +6,16 @@ import org.bukkit.entity.Player; * A sign creation request represents the state where a player has used the create command, but not clicked a sign */ public class SignCreationRequest implements Comparable { - + private final PermissionSign permissionSign; private final Player player; private final long initiationTime; /** * Instantiates a new sign creation request - * + * * @param permissionSign

The sign which is about to be created

- * @param player

The player starting to create the permission sign

+ * @param player

The player starting to create the permission sign

* @param initiationTime

*/ public SignCreationRequest(PermissionSign permissionSign, Player player, long initiationTime) { @@ -26,7 +26,7 @@ public class SignCreationRequest implements Comparable { /** * Gets the permission sign involved in this request - * + * * @return

The involved permission sign

*/ public PermissionSign getPermissionSign() { @@ -35,7 +35,7 @@ public class SignCreationRequest implements Comparable { /** * Gets the player involved in this request - * + * * @return

The involved player

*/ public Player getPlayer() { @@ -44,13 +44,13 @@ public class SignCreationRequest implements Comparable { /** * Gets the time this sign creation request was initiated - * + * * @return

The time this request was initiated

*/ public long initiationTime() { return this.initiationTime; } - + @Override public boolean equals(Object other) { if (!(other instanceof SignCreationRequest otherRequest)) { @@ -59,7 +59,7 @@ public class SignCreationRequest implements Comparable { if (this == other) { return true; } - + return this.getPlayer().getUniqueId() == otherRequest.getPlayer().getUniqueId(); } diff --git a/src/main/java/net/knarcraft/permissionsigns/formatting/StringFormatter.java b/src/main/java/net/knarcraft/permissionsigns/formatting/StringFormatter.java new file mode 100644 index 0000000..969a853 --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/formatting/StringFormatter.java @@ -0,0 +1,40 @@ +package net.knarcraft.permissionsigns.formatting; + +import org.bukkit.ChatColor; + +/** + * A formatter for formatting displayed messages + */ +public class StringFormatter { + + /** + * Formats an information message by adding the prefix and text color + * + * @param message

The message to format

+ * @return

The formatted message

+ */ + public static String formatInfoMessage(String message) { + return ChatColor.DARK_RED + formatMessage(message); + } + + /** + * Formats an error message by adding the prefix and text color + * + * @param message

The message to format

+ * @return

The formatted message

+ */ + public static String formatErrorMessage(String message) { + return ChatColor.DARK_GREEN + formatMessage(message); + } + + /** + * Formats a message by adding the prefix and text color + * + * @param message

The message to format

+ * @return

The formatted message

+ */ + private static String formatMessage(String message) { + return Translator.getTranslatedMessage(TranslatableMessage.PREFIX) + ChatColor.GRAY + message; + } + +} diff --git a/src/main/java/net/knarcraft/permissionsigns/formatting/TranslatableMessage.java b/src/main/java/net/knarcraft/permissionsigns/formatting/TranslatableMessage.java new file mode 100644 index 0000000..dc8487c --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/formatting/TranslatableMessage.java @@ -0,0 +1,19 @@ +package net.knarcraft.permissionsigns.formatting; + +/** + * An enum representing all translatable messages + */ +public enum TranslatableMessage { + + PREFIX, + MISSING_CREATION_INFO, + TIME_UNIT, + COST_FREE, + PERMANENT, + COST_INVALID_NUMBER, + DURATION_INVALID_NUMBER, + COMMAND_PLAYER_ONLY, + PERMISSION_SIGN_DESTROY_DENY, + 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 new file mode 100644 index 0000000..2c1c84b --- /dev/null +++ b/src/main/java/net/knarcraft/permissionsigns/formatting/Translator.java @@ -0,0 +1,67 @@ +package net.knarcraft.permissionsigns.formatting; + +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +/** + * A tool to get strings translated to the correct language + */ +public class Translator { + + private static Map translatedMessages; + private static Map backupTranslatedMessages; + + /** + * Loads the languages used by this translator + */ + public Translator() { + backupTranslatedMessages = loadTranslatedMessages("en"); + translatedMessages = loadTranslatedMessages("en"); + } + + /** + * Gets a translated version of the given translatable message + * + * @param translatableMessage

The message to translate

+ * @return

The translated message

+ */ + public static String getTranslatedMessage(TranslatableMessage translatableMessage) { + if (translatedMessages.containsKey(translatableMessage)) { + return translatedMessages.get(translatableMessage); + } else if (backupTranslatedMessages.containsKey(translatableMessage)) { + return backupTranslatedMessages.get(translatableMessage); + } else { + return translatableMessage.toString(); + } + } + + /** + * Loads all translated messages for the given language + * + * @param language

The language chosen by the user

+ * @return

A mapping of all strings for the given language

+ */ + 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 = new BufferedReader(new InputStreamReader(inputStream)); + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader); + + for (TranslatableMessage message : TranslatableMessage.values()) { + String translated = configuration.getString(language + "." + message.toString()); + if (translated != null) { + translatedMessages.put(message, translated); + } + } + return translatedMessages; + } + +} \ No newline at end of file diff --git a/src/main/java/net/knarcraft/permissionsigns/listener/SignListener.java b/src/main/java/net/knarcraft/permissionsigns/listener/SignListener.java index bd9465f..8da85c4 100644 --- a/src/main/java/net/knarcraft/permissionsigns/listener/SignListener.java +++ b/src/main/java/net/knarcraft/permissionsigns/listener/SignListener.java @@ -2,6 +2,8 @@ package net.knarcraft.permissionsigns.listener; import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.container.SignCreationRequest; +import net.knarcraft.permissionsigns.formatting.TranslatableMessage; +import net.knarcraft.permissionsigns.formatting.Translator; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; @@ -14,6 +16,9 @@ import org.bukkit.event.player.PlayerInteractEvent; import java.util.Arrays; +/** + * A listener for all events related to signs + */ public class SignListener implements Listener { /** @@ -29,26 +34,46 @@ public class SignListener implements Listener { if (block == null) { return; } - + Material material = block.getBlockData().getMaterial(); if (!Tag.SIGNS.isTagged(material) && !Tag.WALL_SIGNS.isTagged(material)) { return; } + Sign sign = (Sign) block.getState(); if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { - Sign sign = (Sign) block.getState(); handleSignRightClick(sign, player); + } else if (event.getAction() == Action.LEFT_CLICK_BLOCK) { + handleSignLeftClick(sign, player, event); + } + } + + private void handleSignLeftClick(Sign sign, Player player, PlayerInteractEvent event) { + //TODO: Check if the sign is a registered permissions sign + boolean registered = true; + if (!registered) { + return; + } + if (!player.hasPermission("permissionsigns.admin")) { + event.setCancelled(true); + player.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.PERMISSION_SIGN_DESTROY_DENY)); + } else { + //TODO: Un-register the permissions sign + player.sendMessage(Translator.getTranslatedMessage(TranslatableMessage.PERMISSION_SIGN_REMOVED)); } } /** * Handles the right-clicking action - * - * @param sign

The clicked sign

+ * + * @param sign

The clicked sign

* @param player

The player that clicked the sign

*/ private void handleSignRightClick(Sign sign, Player player) { String[] lines = sign.getLines(); + + //TODO: Check if the sign is a registered permissions sign + //Don't allow non-empty signs to be overwritten if (!Arrays.stream(lines).allMatch(String::isEmpty)) { return; @@ -61,5 +86,5 @@ public class SignListener implements Listener { //TODO: Register the sign and remove the request } - + } diff --git a/src/main/java/net/knarcraft/permissionsigns/thread/SignCreationRequestTimeoutThread.java b/src/main/java/net/knarcraft/permissionsigns/thread/SignCreationRequestTimeoutThread.java index 0fd7bb2..ce43587 100644 --- a/src/main/java/net/knarcraft/permissionsigns/thread/SignCreationRequestTimeoutThread.java +++ b/src/main/java/net/knarcraft/permissionsigns/thread/SignCreationRequestTimeoutThread.java @@ -8,23 +8,23 @@ import java.util.Queue; * The sign creation request timeout thread is responsible for removing sign creation requests as they time out */ public class SignCreationRequestTimeoutThread implements Runnable { - + private final Queue signCreationRequests; /** * Instantiates a new sign creation request timeout thread - * + * * @param signCreationRequests

A pointer to the queue of sign creation requests

*/ public SignCreationRequestTimeoutThread(Queue signCreationRequests) { this.signCreationRequests = signCreationRequests; } - + @Override public void run() { long currentTime = System.currentTimeMillis(); - int requestTimeoutSeconds = 20; - + int requestTimeoutSeconds = 60; + SignCreationRequest firstElement = signCreationRequests.peek(); while (firstElement != null && currentTime > firstElement.initiationTime() + (1000 * requestTimeoutSeconds)) { //Remove any expired sign creation requests @@ -32,5 +32,5 @@ public class SignCreationRequestTimeoutThread implements Runnable { firstElement = signCreationRequests.peek(); } } - + } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 6eb1c99..90c0f18 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,17 +1,35 @@ name: PermissionSigns version: '${project.version}' main: net.knarcraft.permissionsigns.Permissionsigns -api-version: 1.17 +api-version: 1.18 prefix: PermissionSigns depend: [ Vault ] authors: [ EpicKnarvik97 ] description: A plugin for selling permissions using signs website: git.knarcraft.net - -permissions: +commands: + permissionsigns: + aliases: + - ps + - permsigns + - permsign + - signperm + - signperms + description: Used for all permission sign commands + usage: / - Used for all permission sign commands +permissions: permissionsigns.use: description: Allows players to use the permission signs default: true permissionsigns.admin: + description: Allows all administrative tasks such as creating permission signs and reloading + default: op + children: + permissionsigns.admin.reload: true + permissionsigns.admin.create: true + permissionsigns.admin.reload: + description: Allows the usage of the /reload command + default: op + permissionsigns.admin.create: description: Allows players to create/destroy permissionsigns default: op \ No newline at end of file diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml new file mode 100644 index 0000000..b40e53a --- /dev/null +++ b/src/main/resources/strings.yml @@ -0,0 +1,11 @@ +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