diff --git a/src/main/java/net/knarcraft/minigames/MiniGames.java b/src/main/java/net/knarcraft/minigames/MiniGames.java
index 40e97c7..7521db5 100644
--- a/src/main/java/net/knarcraft/minigames/MiniGames.java
+++ b/src/main/java/net/knarcraft/minigames/MiniGames.java
@@ -325,6 +325,11 @@ public final class MiniGames extends JavaPlugin {
log(Level.WARNING, "Unable to register PlaceholderAPI parkour expansion!");
}
}
+ if (Bukkit.getPluginManager().getPlugin("Vault") != null) {
+ setupVault();
+ } else {
+ log(Level.WARNING, "Vault not found. Economy and Permission rewards are unavailable.");
+ }
}
/**
diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/CommandReward.java b/src/main/java/net/knarcraft/minigames/arena/reward/CommandReward.java
index c246dda..a810022 100644
--- a/src/main/java/net/knarcraft/minigames/arena/reward/CommandReward.java
+++ b/src/main/java/net/knarcraft/minigames/arena/reward/CommandReward.java
@@ -27,8 +27,7 @@ public class CommandReward implements Reward {
@Override
public boolean grant(@NotNull Player player) {
- return Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(),
- command.replaceAll("[<%(\\[]player(_|-name)?[>%)\\]]", player.getName()));
+ return Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), replaceNamePlaceholder(player, command));
}
@Override
@@ -45,6 +44,17 @@ public class CommandReward implements Reward {
return data;
}
+ /**
+ * Replaces the name placeholder in the given input with the given player's name
+ *
+ * @param player
The player whose name should be used
+ * @param input The input containing a name placeholder
+ * @return The input with the placeholder replaced
+ */
+ private String replaceNamePlaceholder(@NotNull Player player, @NotNull String input) {
+ return input.replaceAll("[<%(\\[{]player[_\\-]?(name)?[>%)\\]}]", player.getName());
+ }
+
/**
* Deserializes the command reward defined in the given data
*
diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/ItemReward.java b/src/main/java/net/knarcraft/minigames/arena/reward/ItemReward.java
index 2247fc9..fde135b 100644
--- a/src/main/java/net/knarcraft/minigames/arena/reward/ItemReward.java
+++ b/src/main/java/net/knarcraft/minigames/arena/reward/ItemReward.java
@@ -45,7 +45,7 @@ public class ItemReward implements Reward {
public @NotNull String getGrantMessage() {
return MiniGames.getInstance().getStringFormatter().replacePlaceholders(MiniGameMessage.SUCCESS_ITEM_REWARDED,
new String[]{"{amount}", "{item}"}, new String[]{String.valueOf(item.getAmount()),
- item.getType().getKey().getKey()});
+ item.getType().getKey().getKey().replace("_", " ")});
}
@NotNull
diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/RewardType.java b/src/main/java/net/knarcraft/minigames/arena/reward/RewardType.java
index 0da99c9..c3778ca 100644
--- a/src/main/java/net/knarcraft/minigames/arena/reward/RewardType.java
+++ b/src/main/java/net/knarcraft/minigames/arena/reward/RewardType.java
@@ -1,7 +1,6 @@
package net.knarcraft.minigames.arena.reward;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* The type of a specific reward
@@ -11,46 +10,24 @@ public enum RewardType {
/**
* A command reward
*/
- COMMAND(CommandReward.class),
+ COMMAND,
/**
* An economy reward
*/
- ECONOMY(EconomyReward.class),
+ ECONOMY,
/**
* An item reward
*/
- ITEM(ItemReward.class),
+ ITEM,
/**
* A permission reward
*/
- PERMISSION(PermissionReward.class),
+ PERMISSION,
;
- private final Class> classType;
-
- RewardType(Class> classType) {
- this.classType = classType;
- }
-
- /**
- * Gets the type of reward the given object represents
- *
- * @param object A reward object
- * @return The reward type of the given object, or null if not recognized
- */
- public static @Nullable RewardType getFromObject(@NotNull K object) {
- for (RewardType rewardType : RewardType.values()) {
- if (object.getClass() == rewardType.classType) {
- return rewardType;
- }
- }
-
- return null;
- }
-
/**
* Gets a reward type from the given string
*
diff --git a/src/main/java/net/knarcraft/minigames/command/JoinArenaTabCompleter.java b/src/main/java/net/knarcraft/minigames/command/JoinArenaTabCompleter.java
index d33828e..a6f592c 100644
--- a/src/main/java/net/knarcraft/minigames/command/JoinArenaTabCompleter.java
+++ b/src/main/java/net/knarcraft/minigames/command/JoinArenaTabCompleter.java
@@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* An abstract class for an arena joining tab-completer
diff --git a/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java b/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java
index 2537618..e96a50a 100644
--- a/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java
+++ b/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java
@@ -1,23 +1,168 @@
package net.knarcraft.minigames.command;
+import net.knarcraft.knarlib.util.MaterialHelper;
+import net.knarcraft.knarlib.util.TabCompletionHelper;
+import net.knarcraft.minigames.MiniGames;
+import net.knarcraft.minigames.arena.Arena;
+import net.knarcraft.minigames.arena.reward.RewardCondition;
+import net.knarcraft.minigames.arena.reward.RewardType;
+import net.knarcraft.minigames.util.TabCompleteHelper;
+import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
import java.util.List;
+import java.util.Set;
+
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingStartsWith;
/**
* The tab completer for the reward setting command
*/
public class SetArenaRewardTabCompleter implements TabCompleter {
+ private static final List materials = getMaterials();
+
@Nullable
@Override
public List onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
- @NotNull String[] strings) {
- return null;
+ @NotNull String[] arguments) {
+ if (arguments.length == 1) {
+ // The first argument is either clear or add
+ return TabCompletionHelper.filterMatchingStartsWith(Arrays.asList("add", "clear"), arguments[0]);
+ }
+ if (arguments.length >= 2) {
+ // If the first argument is invalid, stop further tab completion
+ if (!arguments[0].equalsIgnoreCase("add") && !arguments[0].equalsIgnoreCase("clear")) {
+ return new ArrayList<>();
+ }
+ }
+ if (arguments.length == 2) {
+ // The second argument is the type of arena to change rewards for
+ return TabCompletionHelper.filterMatchingStartsWith(Arrays.asList("dropper", "parkour"), arguments[1]);
+ } else if (arguments.length == 3) {
+ // The third argument is the name of the arena to change rewards for
+ if (arguments[1].equalsIgnoreCase("dropper")) {
+ return filterMatchingContains(TabCompleteHelper.getDropperArenas(), arguments[2]);
+ } else if (arguments[1].equalsIgnoreCase("parkour")) {
+ return filterMatchingContains(TabCompleteHelper.getParkourArenas(), arguments[2]);
+ }
+ }
+ if (arguments.length >= 4) {
+ // Make sure a valid dropper or arena name has been given
+ Arena arena = null;
+ if (arguments[1].equalsIgnoreCase("dropper")) {
+ arena = MiniGames.getInstance().getDropperArenaHandler().getArena(arguments[2]);
+ } else if (arguments[1].equalsIgnoreCase("parkour")) {
+ arena = MiniGames.getInstance().getParkourArenaHandler().getArena(arguments[2]);
+ }
+ if (arena == null) {
+ return new ArrayList<>();
+ }
+ }
+ if (arguments.length == 4) {
+ // The fourth argument is the condition to change the reward for
+ return filterMatchingContains(getRewardConditions(), arguments[3]);
+ }
+ if (arguments.length >= 5) {
+ // If the condition is invalid, or it's the clear action, stop tab-completion
+ if (RewardCondition.getFromString(arguments[3]) == null ||
+ arguments[0].equalsIgnoreCase("clear")) {
+ return new ArrayList<>();
+ }
+ }
+ if (arguments.length == 5) {
+ // The fifth argument is the type of reward to grant
+ return filterMatchingContains(getRewardTypes(), arguments[4]);
+ }
+ if (arguments.length >= 6) {
+ // Make sure a valid reward type has been given
+ RewardType rewardType = RewardType.getFromString(arguments[4]);
+ if (rewardType == null) {
+ return new ArrayList<>();
+ }
+
+ if (arguments.length == 6) {
+ return switch (rewardType) {
+ case ITEM -> filterMatchingContains(materials, arguments[5]);
+ case PERMISSION -> TabCompleteHelper.tabCompletePermission(arguments[5]);
+ case ECONOMY -> filterMatchingStartsWith(Arrays.asList("1", "5", "10", "25", "50"), arguments[5]);
+ case COMMAND -> filterMatchingStartsWith(getCommands(), arguments[5]);
+ };
+ }
+
+ if (rewardType == RewardType.ITEM && arguments.length == 7) {
+ // If a valid item material has been given, give potential amounts
+ if (MaterialHelper.loadMaterialString(arguments[5], MiniGames.getInstance().getLogger()) == null) {
+ return new ArrayList<>();
+ }
+ return Arrays.asList("1", "5", "10", "16", "32", "48", "64");
+ }
+ }
+ return new ArrayList<>();
+ }
+
+ /**
+ * Gets example command rewards
+ *
+ * @return Example command rewards
+ */
+ private static List getCommands() {
+ List commands = new ArrayList<>();
+ commands.add("f powerboost player add %player% 1");
+ commands.add("minecraft:xp give (player_name) 1000");
+ return commands;
+ }
+
+ /**
+ * Gets all materials grant-able as item rewards
+ *
+ * @return All grant-able materials
+ */
+ private static List getMaterials() {
+ List materials = new ArrayList<>();
+ Set invalid = EnumSet.of(Material.WATER, Material.LAVA, Material.POWDER_SNOW);
+ for (Material material : Material.values()) {
+ if (material.isAir() || invalid.contains(material) || (material.isBlock() &&
+ (material.getHardness() == -1 || material.getHardness() == Double.MAX_VALUE))) {
+ continue;
+ }
+ materials.add(material.name());
+ }
+ return materials;
+ }
+
+ /**
+ * Gets a list of all reward types
+ *
+ * @return All reward types
+ */
+ private List getRewardTypes() {
+ List types = new ArrayList<>();
+ for (RewardType rewardType : RewardType.values()) {
+ types.add(rewardType.name());
+ }
+ return types;
+ }
+
+ /**
+ * Gets a list of all reward conditions
+ *
+ * @return All reward conditions
+ */
+ private List getRewardConditions() {
+ List conditions = new ArrayList<>();
+ for (RewardCondition rewardCondition : RewardCondition.values()) {
+ conditions.add(rewardCondition.name());
+ }
+ return conditions;
}
}
diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupListCommand.java b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupListCommand.java
index fe654d8..7435921 100644
--- a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupListCommand.java
+++ b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupListCommand.java
@@ -16,7 +16,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The command for listing groups and the stages within
diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java
index d1bfb4d..db67695 100644
--- a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java
+++ b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java
@@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The command for setting the group of an arena
diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSwapCommand.java b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSwapCommand.java
index 404018b..9097a7b 100644
--- a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSwapCommand.java
+++ b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSwapCommand.java
@@ -16,7 +16,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The command for swapping the order of two arenas in a group
diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaTabCompleter.java b/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaTabCompleter.java
index 2488606..52d4951 100644
--- a/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaTabCompleter.java
+++ b/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaTabCompleter.java
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The tab-completer for the edit arena command
diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/RemoveDropperArenaTabCompleter.java b/src/main/java/net/knarcraft/minigames/command/dropper/RemoveDropperArenaTabCompleter.java
index 1143e3e..7a90a1f 100644
--- a/src/main/java/net/knarcraft/minigames/command/dropper/RemoveDropperArenaTabCompleter.java
+++ b/src/main/java/net/knarcraft/minigames/command/dropper/RemoveDropperArenaTabCompleter.java
@@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The tab-completer for the remove arena command
diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaTabCompleter.java b/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaTabCompleter.java
index 3a0a7f0..3aff671 100644
--- a/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaTabCompleter.java
+++ b/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaTabCompleter.java
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The tab-completer for the edit arena command
diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupListCommand.java b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupListCommand.java
index 915a861..2101887 100644
--- a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupListCommand.java
+++ b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupListCommand.java
@@ -17,7 +17,7 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The command for listing groups and the stages within
diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java
index e97081e..81dc3ae 100644
--- a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java
+++ b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java
@@ -17,7 +17,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The command for setting the group of an arena
diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSwapCommand.java b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSwapCommand.java
index f272017..83bd74d 100644
--- a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSwapCommand.java
+++ b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSwapCommand.java
@@ -16,7 +16,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The command for swapping the order of two arenas in a group
diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/RemoveParkourArenaTabCompleter.java b/src/main/java/net/knarcraft/minigames/command/parkour/RemoveParkourArenaTabCompleter.java
index 87c0787..88b4530 100644
--- a/src/main/java/net/knarcraft/minigames/command/parkour/RemoveParkourArenaTabCompleter.java
+++ b/src/main/java/net/knarcraft/minigames/command/parkour/RemoveParkourArenaTabCompleter.java
@@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
-import static net.knarcraft.minigames.util.TabCompleteHelper.filterMatchingContains;
+import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The tab-completer for the remove arena command
diff --git a/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java b/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java
index fee509a..8153c6e 100644
--- a/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java
+++ b/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java
@@ -1,18 +1,22 @@
package net.knarcraft.minigames.util;
+import net.knarcraft.knarlib.util.TabCompletionHelper;
import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.Arena;
import net.knarcraft.minigames.arena.ArenaHandler;
import net.knarcraft.minigames.arena.EditablePropertyType;
import net.knarcraft.minigames.arena.dropper.DropperArenaEditableProperty;
import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty;
+import org.bukkit.Bukkit;
import org.bukkit.Material;
+import org.bukkit.permissions.Permission;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.StringJoiner;
/**
* A helper-class for common tab-completions
@@ -20,6 +24,8 @@ import java.util.Map;
public final class TabCompleteHelper {
private static Map> tabCompleteSuggestions;
+ private static List plugins;
+ private static Map> permissions;
private TabCompleteHelper() {
@@ -82,23 +88,6 @@ public final class TabCompleteHelper {
return arenaProperties;
}
- /**
- * Finds tab complete values that contain the typed text
- *
- * @param values The values to filter
- * @param typedText The text the player has started typing
- * @return The given string values that contain the player's typed text
- */
- public static List filterMatchingContains(@NotNull List values, @NotNull String typedText) {
- List configValues = new ArrayList<>();
- for (String value : values) {
- if (value.toLowerCase().contains(typedText.toLowerCase())) {
- configValues.add(value);
- }
- }
- return configValues;
- }
-
/**
* Gets tab-complete suggestions for the given property type
*
@@ -215,4 +204,65 @@ public final class TabCompleteHelper {
return locations;
}
+ /**
+ * Gets the tab complete value for the permission typed
+ *
+ * @param typedNode The full permission node typed by the player
+ * @return All known valid auto-complete options
+ */
+ public static List tabCompletePermission(String typedNode) {
+ if (plugins == null) {
+ loadAvailablePermissions();
+ }
+ List output;
+ if (typedNode.contains(".")) {
+ List matchingPermissions = permissions.get(typedNode.substring(0, typedNode.lastIndexOf(".")));
+ if (matchingPermissions == null) {
+ output = new ArrayList<>();
+ } else {
+ //Filter by the typed text
+ output = TabCompletionHelper.filterMatchingStartsWith(matchingPermissions, typedNode);
+ }
+ } else {
+ output = plugins;
+ }
+
+ //Add previous permissions in the comma-separated lists as a prefix
+ return output;
+ }
+
+ /**
+ * Loads all permissions available from bukkit plugins
+ */
+ private static void loadAvailablePermissions() {
+ plugins = new ArrayList<>();
+ permissions = new HashMap<>();
+
+ for (Permission permission : Bukkit.getPluginManager().getPermissions()) {
+ loadPermission(permission.getName());
+ }
+ }
+
+ /**
+ * Loads a given permission into the proper lists and maps
+ *
+ * @param permissionName The permission to load
+ */
+ private static void loadPermission(String permissionName) {
+ String[] permissionParts = permissionName.split("\\.");
+ if (permissionParts.length == 1 && !plugins.contains(permissionParts[0])) {
+ plugins.add(permissionParts[0]);
+ } else if (permissionParts.length > 1) {
+ StringJoiner pathJoiner = new StringJoiner(".");
+ for (int j = 0; j < permissionParts.length - 1; j++) {
+ pathJoiner.add(permissionParts[j]);
+ }
+ String path = pathJoiner.toString();
+ List permissionList = permissions.computeIfAbsent(path, k -> new ArrayList<>());
+ permissionList.add(permissionName);
+
+ loadPermission(path);
+ }
+ }
+
}