Adds tab completion for the creation command, and fixes several bugs
This commit is contained in:
parent
5c2831bbb7
commit
252d3ed88a
2
pom.xml
2
pom.xml
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.knarcraft</groupId>
|
||||
<artifactId>permissionsigns</artifactId>
|
||||
<artifactId>PermissionSigns</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
@ -5,8 +5,10 @@ import net.knarcraft.permissionsigns.command.PermissionSignsTabCompleter;
|
||||
import net.knarcraft.permissionsigns.container.PermissionSign;
|
||||
import net.knarcraft.permissionsigns.container.SignCreationRequest;
|
||||
import net.knarcraft.permissionsigns.formatting.Translator;
|
||||
import net.knarcraft.permissionsigns.listener.SignListener;
|
||||
import net.knarcraft.permissionsigns.manager.EconomyManager;
|
||||
import net.knarcraft.permissionsigns.manager.PermissionManager;
|
||||
import net.knarcraft.permissionsigns.manager.SignManager;
|
||||
import net.knarcraft.permissionsigns.thread.SignCreationRequestTimeoutThread;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
@ -19,6 +21,7 @@ import org.bukkit.plugin.ServicesManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Queue;
|
||||
@ -94,8 +97,10 @@ public final class PermissionSigns extends JavaPlugin {
|
||||
Stream<SignCreationRequest> matchingRequests = signCreationRequests.stream().filter(
|
||||
(item) -> item.getPlayer().getUniqueId().equals(uuid));
|
||||
List<SignCreationRequest> requestList = matchingRequests.toList();
|
||||
if (requestList.size() > 0) {
|
||||
signCreationRequests.remove(requestList.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@ -153,11 +158,13 @@ public final class PermissionSigns extends JavaPlugin {
|
||||
} else {
|
||||
throw new IllegalStateException("[PermissionSigns] Error: Vault could not be loaded");
|
||||
}
|
||||
getServer().getPluginManager().registerEvents(new SignListener(), this);
|
||||
|
||||
Translator.loadLanguages("en");
|
||||
registerCommands();
|
||||
BukkitScheduler scheduler = Bukkit.getScheduler();
|
||||
scheduler.runTaskTimer(this, new SignCreationRequestTimeoutThread(signCreationRequests), 0L, 100L);
|
||||
SignManager.loadSigns();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -173,7 +180,11 @@ public final class PermissionSigns extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Plugin shutdown logic
|
||||
try {
|
||||
SignManager.saveSigns();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public class CreateCommand implements CommandExecutor {
|
||||
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
|
||||
//Name and permission(s) required, but duration and cost optional
|
||||
String usage = "/ps create <name> <permission,permission> [cost] [duration] - Used for creating a new permission sign";
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COMMAND_PLAYER_ONLY));
|
||||
return false;
|
||||
@ -31,12 +32,14 @@ public class CreateCommand implements CommandExecutor {
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.MISSING_CREATION_INFO));
|
||||
return false;
|
||||
sender.sendMessage(usage);
|
||||
return true;
|
||||
}
|
||||
|
||||
PermissionSign newSign = parseSign(sender, args);
|
||||
if (newSign == null) {
|
||||
return false;
|
||||
sender.sendMessage(usage);
|
||||
return true;
|
||||
}
|
||||
PermissionSigns.addSignCreationRequest((Player) sender, newSign);
|
||||
|
||||
@ -54,20 +57,24 @@ public class CreateCommand implements CommandExecutor {
|
||||
private PermissionSign parseSign(@NotNull CommandSender sender, @NotNull String[] args) {
|
||||
String name = args[0];
|
||||
String[] permissions = args[1].split(",");
|
||||
double cost;
|
||||
int duration;
|
||||
double cost = 0;
|
||||
int duration = 0;
|
||||
if (args.length > 2) {
|
||||
try {
|
||||
cost = Double.parseDouble(args[2]);
|
||||
} catch (NumberFormatException exception) {
|
||||
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COST_INVALID_NUMBER));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (args.length > 3) {
|
||||
try {
|
||||
duration = Integer.parseInt(args[3]);
|
||||
} catch (NumberFormatException exception) {
|
||||
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.DURATION_INVALID_NUMBER));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new PermissionSign(name, List.of(permissions), duration, cost);
|
||||
}
|
||||
|
@ -1,20 +1,159 @@
|
||||
package net.knarcraft.permissionsigns.command;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The tab completer for the create command
|
||||
*/
|
||||
public class CreateTabCompleter implements TabCompleter {
|
||||
|
||||
private static List<String> plugins;
|
||||
private static Map<String, List<String>> permissions;
|
||||
private static List<String> numbers;
|
||||
private static List<String> empty;
|
||||
private static List<String> name;
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
|
||||
return null;
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias,
|
||||
@NotNull String[] args) {
|
||||
//First, display all plugins, filtering on written text
|
||||
//Second, if a dot has been input, go to the correct branch,
|
||||
//Might want to save the plugin list, but generate permission lists on the fly as needed
|
||||
if (plugins == null) {
|
||||
loadAvailablePermissions();
|
||||
numbers = new ArrayList<>();
|
||||
numbers.add(String.valueOf(0));
|
||||
empty = new ArrayList<>();
|
||||
name = new ArrayList<>();
|
||||
name.add("<name>");
|
||||
}
|
||||
|
||||
if (args.length > 4) {
|
||||
return empty;
|
||||
} else if (args.length > 2) {
|
||||
return numbers;
|
||||
} else if (args.length > 1) {
|
||||
return tabCompletePermission(args[1]);
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tab complete value for the permission typed
|
||||
*
|
||||
* @param typedNode <p>The full permission node typed by the player</p>
|
||||
* @return <p>All known valid auto-complete options</p>
|
||||
*/
|
||||
private List<String> tabCompletePermission(String typedNode) {
|
||||
StringBuilder permissionListString = new StringBuilder();
|
||||
if (typedNode.contains(",")) {
|
||||
String[] permissionList = typedNode.split(",");
|
||||
for (int i = 0; i < permissionList.length - 1; i++) {
|
||||
permissionListString.append(permissionList[i]);
|
||||
permissionListString.append(",");
|
||||
}
|
||||
typedNode = permissionList[permissionList.length - 1];
|
||||
}
|
||||
String permissionPrefix = permissionListString.toString();
|
||||
List<String> output;
|
||||
if (typedNode.contains(".")) {
|
||||
List<String> matchingPermissions = permissions.get(typedNode.substring(0, typedNode.lastIndexOf(".")));
|
||||
if (matchingPermissions == null) {
|
||||
if (permissionPrefix.isEmpty()) {
|
||||
output = new ArrayList<>();
|
||||
} else {
|
||||
List<String> onlyPrefix = new ArrayList<>();
|
||||
onlyPrefix.add(permissionPrefix);
|
||||
output = onlyPrefix;
|
||||
}
|
||||
} else {
|
||||
//Filter by the typed text
|
||||
output = filterMatching(matchingPermissions, typedNode);
|
||||
}
|
||||
} else {
|
||||
output = plugins;
|
||||
}
|
||||
|
||||
//Add previous permissions in the comma-separated lists as a prefix
|
||||
if (permissionPrefix.isEmpty()) {
|
||||
return output;
|
||||
} else {
|
||||
List<String> prefixed = new ArrayList<>(output.size());
|
||||
for (String matchingCompletion : output) {
|
||||
prefixed.add(permissionPrefix + matchingCompletion);
|
||||
}
|
||||
return prefixed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find completable strings which match the text typed by the command's sender
|
||||
*
|
||||
* @param values <p>The values to filter</p>
|
||||
* @param typedText <p>The text the player has started typing</p>
|
||||
* @return <p>The given string values which start with the player's typed text</p>
|
||||
*/
|
||||
private List<String> filterMatching(List<String> values, String typedText) {
|
||||
List<String> configValues = new ArrayList<>();
|
||||
for (String value : values) {
|
||||
if (value.toLowerCase().startsWith(typedText.toLowerCase())) {
|
||||
configValues.add(value);
|
||||
}
|
||||
}
|
||||
return configValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all permissions available from bukkit plugins
|
||||
*/
|
||||
private static void loadAvailablePermissions() {
|
||||
plugins = new ArrayList<>();
|
||||
permissions = new HashMap<>();
|
||||
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
for (Permission permission : plugin.getDescription().getPermissions()) {
|
||||
loadPermission(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a given permission into the proper lists and maps
|
||||
*
|
||||
* @param permission <p>The permission to load</p>
|
||||
*/
|
||||
private static void loadPermission(Permission permission) {
|
||||
String permissionName = permission.getName();
|
||||
String[] permissionParts = permissionName.split("\\.");
|
||||
for (int i = 0; i < permissionParts.length; i++) {
|
||||
if (i == 0) {
|
||||
plugins.add(permissionParts[0]);
|
||||
} else {
|
||||
StringBuilder pathBuilder = new StringBuilder();
|
||||
for (int j = 0; j < i; j++) {
|
||||
pathBuilder.append(".");
|
||||
pathBuilder.append(permissionParts[j]);
|
||||
}
|
||||
String path = pathBuilder.substring(1);
|
||||
List<String> permissionList = permissions.get(path);
|
||||
if (permissionList == null) {
|
||||
permissionList = new ArrayList<>();
|
||||
permissions.put(pathBuilder.substring(1), permissionList);
|
||||
}
|
||||
permissionList.add(permissionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ public class PermissionSign {
|
||||
return Translator.getTranslatedMessage(TranslatableMessage.SIGN_COST_FREE);
|
||||
} else {
|
||||
String currency = EconomyManager.getCurrency(cost != 1);
|
||||
return String.format("%f%s", cost, currency);
|
||||
return String.format("%.2f%s", cost, currency);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,10 @@ public class StringFormatter {
|
||||
* @param input <p>The input string to replace in</p>
|
||||
* @param placeholder <p>The placeholder to replace</p>
|
||||
* @param replacement <p>The replacement value</p>
|
||||
* @return <p>The input string with all placeholder instances replaced</p>
|
||||
* @return <p>The input string with the placeholder replaced</p>
|
||||
*/
|
||||
public static String replacePlaceholder(String input, String placeholder, String replacement) {
|
||||
return input.replaceAll(placeholder, replacement);
|
||||
return input.replace(placeholder, replacement);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -25,7 +25,7 @@ public class StringFormatter {
|
||||
* @param input <p>The input string to replace in</p>
|
||||
* @param placeholders <p>The placeholders to replace</p>
|
||||
* @param replacements <p>The replacement values</p>
|
||||
* @return <p>The input string with all placeholder instances replaced</p>
|
||||
* @return <p>The input string with placeholders replaced</p>
|
||||
*/
|
||||
public static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
|
||||
for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
|
||||
@ -61,7 +61,7 @@ public class StringFormatter {
|
||||
* @return <p>The formatted message</p>
|
||||
*/
|
||||
public static String formatInfoMessage(String message) {
|
||||
return ChatColor.DARK_RED + formatMessage(message);
|
||||
return ChatColor.DARK_GREEN + formatMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,7 +71,7 @@ public class StringFormatter {
|
||||
* @return <p>The formatted message</p>
|
||||
*/
|
||||
public static String formatErrorMessage(String message) {
|
||||
return ChatColor.DARK_GREEN + formatMessage(message);
|
||||
return ChatColor.DARK_RED + formatMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +82,8 @@ public class StringFormatter {
|
||||
*/
|
||||
private static String formatMessage(String message) {
|
||||
return ChatColor.translateAlternateColorCodes('&',
|
||||
Translator.getTranslatedMessage(TranslatableMessage.PREFIX)) + ChatColor.RESET + message;
|
||||
Translator.getTranslatedMessage(TranslatableMessage.PREFIX)) + " " + ChatColor.RESET +
|
||||
ChatColor.translateAlternateColorCodes('&', message);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -135,7 +135,11 @@ public class SignListener implements Listener {
|
||||
if (!player.hasPermission(permissionNode)) {
|
||||
permissionsBuilder.append(permissionNode);
|
||||
permissionsBuilder.append(", ");
|
||||
PermissionManager.addPermission(player, permissionNode, permissionSign.getDuration() == 0);
|
||||
if (permissionSign.getDuration() == 0) {
|
||||
PermissionManager.addPermission(player, permissionNode);
|
||||
} else {
|
||||
PermissionManager.addTemporaryPermission(player, permissionNode, permissionSign.getDuration());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +148,7 @@ public class SignListener implements Listener {
|
||||
grantedPermissions = grantedPermissions.substring(0, grantedPermissions.length() - 2);
|
||||
String timeUnit = Translator.getTranslatedMessage(TranslatableMessage.SIGN_TIME_UNIT);
|
||||
player.sendMessage(StringFormatter.replacePlaceholders(successMessage, new String[]{"{permissions}", "{time}"},
|
||||
new String[]{grantedPermissions, permissionSign.getDuration() + timeUnit}));
|
||||
new String[]{grantedPermissions, permissionSign.getDuration() + " " + timeUnit}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,28 +24,13 @@ public class PermissionManager {
|
||||
PermissionManager.permission = permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants a permission to the given player
|
||||
*
|
||||
* @param player <p>The player to grant the permission to</p>
|
||||
* @param permissionNode <p>The permission node to grant the player</p>
|
||||
* @param permanent <p>Whether to permanently grant the permission node</p>
|
||||
*/
|
||||
public static void addPermission(Player player, String permissionNode, boolean permanent) {
|
||||
if (permanent) {
|
||||
addPermission(player, permissionNode);
|
||||
} else {
|
||||
addTemporaryPermission(player, permissionNode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants a permanent permission to a player
|
||||
*
|
||||
* @param player <p>The player to grant the permission to</p>
|
||||
* @param permissionNode <p>The permission node to grant to the player</p>
|
||||
*/
|
||||
private static void addPermission(Player player, String permissionNode) {
|
||||
public static void addPermission(Player player, String permissionNode) {
|
||||
permission.playerAdd(player, permissionNode);
|
||||
}
|
||||
|
||||
@ -54,9 +39,11 @@ public class PermissionManager {
|
||||
*
|
||||
* @param player <p>The player to give the permission to</p>
|
||||
* @param permissionNode <p>The temporary permission to grant</p>
|
||||
* @param duration <p>The duration for which the player should keep the given permission</p>
|
||||
*/
|
||||
private static void addTemporaryPermission(OfflinePlayer player, String permissionNode) {
|
||||
public static void addTemporaryPermission(OfflinePlayer player, String permissionNode, int duration) {
|
||||
permission.playerAddTransient(player, permissionNode);
|
||||
temporaryPermissions.add(new TemporaryPermission(player, permissionNode, duration));
|
||||
//TODO: Create and store a temporary permission
|
||||
// Check all stored temporary permissions on startup:
|
||||
// * Remove expired temporary permissions
|
||||
|
@ -15,6 +15,7 @@ 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;
|
||||
|
||||
/**
|
||||
@ -81,10 +82,10 @@ public class SignManager {
|
||||
*/
|
||||
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 signs.yml");
|
||||
return;
|
||||
}
|
||||
for (String key : signSection.getKeys(false)) {
|
||||
@ -95,6 +96,7 @@ public class SignManager {
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
PermissionSigns.getInstance().getLogger().log(Level.INFO, "Permission signs finished loading");
|
||||
//TODO: Might want to re-draw signs here in case any signs have changed
|
||||
}
|
||||
|
||||
@ -120,8 +122,9 @@ public class SignManager {
|
||||
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]));
|
||||
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");
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: PermissionSigns
|
||||
version: '${project.version}'
|
||||
main: net.knarcraft.permissionsigns.Permissionsigns
|
||||
version: 1.0
|
||||
main: net.knarcraft.permissionsigns.PermissionSigns
|
||||
api-version: 1.18
|
||||
prefix: PermissionSigns
|
||||
depend: [ Vault ]
|
||||
|
Loading…
Reference in New Issue
Block a user