Performs a lot of various changes

Adds some new command classes
Adds support for several languages
Adds README
Updates Java and Spigot versions
Adds command info and additional permission info to plugin.yml
Implements manual sign creation request cancelling
This commit is contained in:
Kristian Knarvik 2022-01-09 12:12:55 +01:00
parent d210b45ad5
commit 2917905b23
19 changed files with 502 additions and 52 deletions

5
README.md Normal file
View File

@ -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.

10
pom.xml
View File

@ -13,7 +13,7 @@
<description>A plugin for selling permissions using signs</description> <description>A plugin for selling permissions using signs</description>
<properties> <properties>
<java.version>16</java.version> <java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<url>git.knarcraft.net</url> <url>git.knarcraft.net</url>
@ -69,8 +69,14 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.17.1-R0.1-SNAPSHOT</version> <version>1.18.1-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,9 +1,14 @@
package net.knarcraft.permissionsigns; 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.container.SignCreationRequest;
import net.knarcraft.permissionsigns.thread.SignCreationRequestTimeoutThread; import net.knarcraft.permissionsigns.thread.SignCreationRequestTimeoutThread;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
@ -15,7 +20,27 @@ import java.util.stream.Stream;
public final class PermissionSigns extends JavaPlugin { public final class PermissionSigns extends JavaPlugin {
private static Queue<SignCreationRequest> signCreationRequests = new PriorityQueue<>(); private static final Queue<SignCreationRequest> signCreationRequests = new PriorityQueue<>();
private static String pluginVersion;
/**
* Gets the version of this plugin
*
* @return <p>This plugin's version</p>
*/
public static String getPluginVersion() {
return pluginVersion;
}
/**
* Adds a new sign creation request
*
* @param player <p>The player that initiated the sign creation</p>
* @param sign <p>The sign the player is about to create</p>
*/
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 * Gets the sign creation request for the player with the given UUID
@ -34,8 +59,23 @@ public final class PermissionSigns extends JavaPlugin {
} }
} }
/**
* Cancels the sign creation request triggered by the user
*
* @param uuid <p>The UUID of the player to cancel the request for</p>
*/
public static void cancelSignCreationRequest(UUID uuid) {
Stream<SignCreationRequest> matchingRequests = signCreationRequests.stream().filter(
(item) -> item.getPlayer().getUniqueId().equals(uuid));
List<SignCreationRequest> requestList = matchingRequests.toList();
signCreationRequests.remove(requestList.get(0));
}
@Override @Override
public void onEnable() { public void onEnable() {
PluginDescriptionFile pluginDescriptionFile = this.getDescription();
pluginVersion = pluginDescriptionFile.getVersion();
// Plugin startup logic // Plugin startup logic
//TODO: Add commands create, add and remove //TODO: Add commands create, add and remove
@ -72,12 +112,25 @@ public final class PermissionSigns extends JavaPlugin {
//TODO: Check for existence of old permission signs when clicked and register them as new permission signs. If //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. // it has the permissionSigns header and a name matching contents in signdata.yml, add it.
registerCommands();
BukkitScheduler scheduler = Bukkit.getScheduler(); BukkitScheduler scheduler = Bukkit.getScheduler();
scheduler.runTaskTimer(this, new SignCreationRequestTimeoutThread(signCreationRequests), 0L, 100L); 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 @Override
public void onDisable() { public void onDisable() {
// Plugin shutdown logic // Plugin shutdown logic
} }
} }

View File

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

View File

@ -1,14 +1,21 @@
package net.knarcraft.permissionsigns.command; package net.knarcraft.permissionsigns.command;
import net.knarcraft.permissionsigns.PermissionSigns;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; 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 { public class CancelCommand implements CommandExecutor {
@Override @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) {
return false; PermissionSigns.cancelSignCreationRequest(((Player) sender).getUniqueId());
return true;
} }
} }

View File

@ -1,17 +1,55 @@
package net.knarcraft.permissionsigns.command; 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.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; 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 { public class CreateCommand implements CommandExecutor {
@Override @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 <name> <permission,permission> <cost> <duration> to create a new permission-sign // /ps create <name> <permission,permission> <cost> <duration> to create a new permission-sign
//Name and permission(s) required, but duration and cost optional //Name and permission(s) required, but duration and cost optional
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; 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;
}
} }

View File

@ -3,13 +3,17 @@ package net.knarcraft.permissionsigns.command;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter; import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
/**
* The tab completer for the create command
*/
public class CreateTabCompleter implements TabCompleter { public class CreateTabCompleter implements TabCompleter {
@Override @Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
return null; return null;
} }

View File

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

View File

@ -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<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
if (args.length == 1) {
List<String> commands = getAvailableCommands(sender);
List<String> 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 <p>The command sender to get available commands for</p>
* @return <p>The commands available to the command sender</p>
*/
private List<String> getAvailableCommands(CommandSender commandSender) {
List<String> 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;
}
}

View File

@ -0,0 +1,4 @@
package net.knarcraft.permissionsigns.command;
public class ReloadCommand {
}

View File

@ -1,6 +1,8 @@
package net.knarcraft.permissionsigns.container; 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 org.bukkit.Location;
import java.util.ArrayList; import java.util.ArrayList;
@ -30,6 +32,8 @@ public class PermissionSign {
this.signLocation = signLocation; this.signLocation = signLocation;
this.name = name; this.name = name;
this.permissionNodes = new ArrayList<>(permissionNodes); this.permissionNodes = new ArrayList<>(permissionNodes);
//Automatically fix negative values
this.duration = Math.max(0, duration); this.duration = Math.max(0, duration);
this.cost = Math.max(0, cost); this.cost = Math.max(0, cost);
} }
@ -37,11 +41,12 @@ public class PermissionSign {
/** /**
* Instantiates a new permission sign * Instantiates a new permission sign
* *
* @param name <p>The name to display on the permission sign</p>
* @param permissionNodes <p>The permissions granted when this permission sign is used</p> * @param permissionNodes <p>The permissions granted when this permission sign is used</p>
* @param duration <p>The duration, in seconds, until the permission should be revoked. 0 for non-temporary</p> * @param duration <p>The duration, in seconds, until the permission should be revoked. 0 for non-temporary</p>
* @param cost <p>The cost of using this permission sign</p> * @param cost <p>The cost of using this permission sign</p>
*/ */
public PermissionSign(List<String> permissionNodes, int duration, int cost) { public PermissionSign(String name, List<String> permissionNodes, int duration, int cost) {
this.permissionNodes = new ArrayList<>(permissionNodes); this.permissionNodes = new ArrayList<>(permissionNodes);
this.duration = Math.max(0, duration); this.duration = Math.max(0, duration);
this.cost = Math.max(0, cost); this.cost = Math.max(0, cost);
@ -109,6 +114,20 @@ public class PermissionSign {
return this.cost; return this.cost;
} }
/**
* Gets the lines used to represent this permission sign on a sign
*
* @return <p>The lines used to draw this permission sign</p>
*/
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 @Override
public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof PermissionSign)) { if (!(other instanceof PermissionSign)) {
@ -121,4 +140,31 @@ public class PermissionSign {
return this.signLocation.equals(((PermissionSign) other).signLocation); return this.signLocation.equals(((PermissionSign) other).signLocation);
} }
/**
* Gets the string used for displaying this sign's duration
*
* @return <p>The string used for displaying this sign's duration</p>
*/
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 <p>The string used for displaying this sign's cost</p>
*/
private String getCostString() {
if (cost == 0) {
return Translator.getTranslatedMessage(TranslatableMessage.COST_FREE);
} else {
//TODO: Get currency unit from Vault
return cost + "$";
}
}
} }

View File

@ -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 <p>The message to format</p>
* @return <p>The formatted message</p>
*/
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 <p>The message to format</p>
* @return <p>The formatted message</p>
*/
public static String formatErrorMessage(String message) {
return ChatColor.DARK_GREEN + formatMessage(message);
}
/**
* Formats a message by adding the prefix and text color
*
* @param message <p>The message to format</p>
* @return <p>The formatted message</p>
*/
private static String formatMessage(String message) {
return Translator.getTranslatedMessage(TranslatableMessage.PREFIX) + ChatColor.GRAY + message;
}
}

View File

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

View File

@ -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<TranslatableMessage, String> translatedMessages;
private static Map<TranslatableMessage, String> 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 <p>The message to translate</p>
* @return <p>The translated message</p>
*/
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 <p>The language chosen by the user</p>
* @return <p>A mapping of all strings for the given language</p>
*/
public static Map<TranslatableMessage, String> loadTranslatedMessages(String language) {
Map<TranslatableMessage, String> 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;
}
}

View File

@ -2,6 +2,8 @@ package net.knarcraft.permissionsigns.listener;
import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.container.SignCreationRequest; 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.Material;
import org.bukkit.Tag; import org.bukkit.Tag;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -14,6 +16,9 @@ import org.bukkit.event.player.PlayerInteractEvent;
import java.util.Arrays; import java.util.Arrays;
/**
* A listener for all events related to signs
*/
public class SignListener implements Listener { public class SignListener implements Listener {
/** /**
@ -35,9 +40,26 @@ public class SignListener implements Listener {
return; return;
} }
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
Sign sign = (Sign) block.getState(); Sign sign = (Sign) block.getState();
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
handleSignRightClick(sign, player); 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));
} }
} }
@ -49,6 +71,9 @@ public class SignListener implements Listener {
*/ */
private void handleSignRightClick(Sign sign, Player player) { private void handleSignRightClick(Sign sign, Player player) {
String[] lines = sign.getLines(); String[] lines = sign.getLines();
//TODO: Check if the sign is a registered permissions sign
//Don't allow non-empty signs to be overwritten //Don't allow non-empty signs to be overwritten
if (!Arrays.stream(lines).allMatch(String::isEmpty)) { if (!Arrays.stream(lines).allMatch(String::isEmpty)) {
return; return;

View File

@ -23,7 +23,7 @@ public class SignCreationRequestTimeoutThread implements Runnable {
@Override @Override
public void run() { public void run() {
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
int requestTimeoutSeconds = 20; int requestTimeoutSeconds = 60;
SignCreationRequest firstElement = signCreationRequests.peek(); SignCreationRequest firstElement = signCreationRequests.peek();
while (firstElement != null && currentTime > firstElement.initiationTime() + (1000 * requestTimeoutSeconds)) { while (firstElement != null && currentTime > firstElement.initiationTime() + (1000 * requestTimeoutSeconds)) {

View File

@ -1,17 +1,35 @@
name: PermissionSigns name: PermissionSigns
version: '${project.version}' version: '${project.version}'
main: net.knarcraft.permissionsigns.Permissionsigns main: net.knarcraft.permissionsigns.Permissionsigns
api-version: 1.17 api-version: 1.18
prefix: PermissionSigns prefix: PermissionSigns
depend: [ Vault ] depend: [ Vault ]
authors: [ EpicKnarvik97 ] authors: [ EpicKnarvik97 ]
description: A plugin for selling permissions using signs description: A plugin for selling permissions using signs
website: git.knarcraft.net website: git.knarcraft.net
commands:
permissionsigns:
aliases:
- ps
- permsigns
- permsign
- signperm
- signperms
description: Used for all permission sign commands
usage: /<command> <about/create/cancel/reload> - Used for all permission sign commands
permissions: permissions:
permissionsigns.use: permissionsigns.use:
description: Allows players to use the permission signs description: Allows players to use the permission signs
default: true default: true
permissionsigns.admin: 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 description: Allows players to create/destroy permissionsigns
default: op default: op

View File

@ -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"