From 211833a1885fa29857b3973fb90f739210e60b0c Mon Sep 17 00:00:00 2001 From: Sn0wStorm Date: Tue, 24 Nov 2020 12:48:43 +0100 Subject: [PATCH] Added Tab Completer, with perms cache --- README.md | 9 +- pom.xml | 20 +-- src/com/dre/brewery/P.java | 3 + .../brewery/listeners/CommandListener.java | 34 ++-- .../dre/brewery/listeners/PlayerListener.java | 3 + .../dre/brewery/listeners/TabListener.java | 154 +++++++++++++++--- src/com/dre/brewery/recipe/BRecipe.java | 18 +- .../dre/brewery/utility/PermissionUtil.java | 125 ++++++++++++++ 8 files changed, 304 insertions(+), 62 deletions(-) create mode 100644 src/com/dre/brewery/utility/PermissionUtil.java diff --git a/README.md b/README.md index d8fa754..541be79 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,15 @@ Also see [Wiki](https://github.com/DieReicheErethons/Brewery/wiki) | [Releases] ```XML - brewery-repo - https://zebradrive.de/maven/ + jitpack.io + https://jitpack.io - com.de + com.github.DieReicheErethons Brewery - 2.1.2 + 2.1.3 provided ``` +_For older maven releases see [here](https://github.com/DieReicheErethons/Brewery/blob/v2.1.2/README.md)_ diff --git a/pom.xml b/pom.xml index 4c168f8..b9fbcef 100644 --- a/pom.xml +++ b/pom.xml @@ -89,13 +89,14 @@ http://maven.sk89q.com/repo/ - + jitpack.io https://jitpack.io - brewery-repo - https://zebradrive.de/maven/ + + ender-repo + https://ci.ender.zone/plugin/repository/everything/ chestshop-repo @@ -190,9 +191,9 @@ - com.griefcraft - entitylwc - 2.1 + com.griefcraft.lwc + LWCX + 2.2.6 provided @@ -263,11 +264,4 @@ compile - - - - file-repo - file:///var/tmp/MavenRepo - - diff --git a/src/com/dre/brewery/P.java b/src/com/dre/brewery/P.java index 432791e..f9da3f8 100644 --- a/src/com/dre/brewery/P.java +++ b/src/com/dre/brewery/P.java @@ -215,6 +215,9 @@ public class P extends JavaPlugin { // Reload Cauldron Particle Recipes BCauldron.reload(); + // Clear Recipe completions + TabListener.reload(); + // Reload Recipes boolean successful = true; for (Brew brew : Brew.legacyPotions.values()) { diff --git a/src/com/dre/brewery/listeners/CommandListener.java b/src/com/dre/brewery/listeners/CommandListener.java index d729850..5f799aa 100644 --- a/src/com/dre/brewery/listeners/CommandListener.java +++ b/src/com/dre/brewery/listeners/CommandListener.java @@ -7,6 +7,7 @@ import com.dre.brewery.recipe.BRecipe; import com.dre.brewery.recipe.Ingredient; import com.dre.brewery.recipe.RecipeItem; import com.dre.brewery.utility.BUtil; +import com.dre.brewery.utility.PermissionUtil; import com.dre.brewery.utility.Tuple; import org.bukkit.Material; import org.bukkit.command.Command; @@ -22,6 +23,8 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Locale; +import static com.dre.brewery.utility.PermissionUtil.BPermission.*; + public class CommandListener implements CommandExecutor { public P p = P.p; @@ -194,46 +197,51 @@ public class CommandListener implements CommandExecutor { ArrayList cmds = new ArrayList<>(); cmds.add(p.languageReader.get("Help_Help")); + PermissionUtil.evaluateExtendedPermissions(sender); - if (sender.hasPermission("brewery.cmd.player")) { + if (PLAYER.checkCached(sender)) { cmds.add (p.languageReader.get("Help_Player")); } - if (sender.hasPermission("brewery.cmd.info")) { + if (INFO.checkCached(sender)) { cmds.add (p.languageReader.get("Help_Info")); } - if (P.use1_13 && sender.hasPermission("brewery.cmd.seal")) { + if (P.use1_13 && SEAL.checkCached(sender)) { cmds.add (p.languageReader.get("Help_Seal")); } - if (sender.hasPermission("brewery.cmd.unlabel")) { + if (UNLABEL.checkCached(sender)) { cmds.add (p.languageReader.get("Help_UnLabel")); } - if (sender.hasPermission("brewery.cmd.infoOther")) { + if (PermissionUtil.noExtendedPermissions(sender)) { + return cmds; + } + + if (INFO_OTHER.checkCached(sender)) { cmds.add (p.languageReader.get("Help_InfoOther")); } - if (sender.hasPermission("brewery.cmd.create")) { + if (CREATE.checkCached(sender)) { cmds.add(p.languageReader.get("Help_Create")); cmds.add(p.languageReader.get("Help_Give")); } - if (sender.hasPermission("brewery.cmd.drink") || sender.hasPermission("brewery.cmd.drinkOther")) { + if (DRINK.checkCached(sender) || DRINK_OTHER.checkCached(sender)) { cmds.add(p.languageReader.get("Help_Drink")); } - if (sender.hasPermission("brewery.cmd.reload")) { + if (RELOAD.checkCached(sender)) { cmds.add(p.languageReader.get("Help_Configname")); cmds.add(p.languageReader.get("Help_Reload")); } - if (sender.hasPermission("brewery.cmd.puke") || sender.hasPermission("brewery.cmd.pukeOther")) { + if (PUKE.checkCached(sender) || PUKE_OTHER.checkCached(sender)) { cmds.add(p.languageReader.get("Help_Puke")); } - if (sender.hasPermission("brewery.cmd.wakeup")) { + if (WAKEUP.checkCached(sender)) { cmds.add(p.languageReader.get("Help_Wakeup")); cmds.add(p.languageReader.get("Help_WakeupList")); cmds.add(p.languageReader.get("Help_WakeupCheck")); @@ -242,15 +250,15 @@ public class CommandListener implements CommandExecutor { cmds.add(p.languageReader.get("Help_WakeupRemove")); } - if (sender.hasPermission("brewery.cmd.static")) { + if (STATIC.checkCached(sender)) { cmds.add(p.languageReader.get("Help_Static")); } - if (sender.hasPermission("brewery.cmd.copy")) { + if (COPY.checkCached(sender)) { cmds.add (p.languageReader.get("Help_Copy")); } - if (sender.hasPermission("brewery.cmd.delete")) { + if (DELETE.checkCached(sender)) { cmds.add (p.languageReader.get("Help_Delete")); } diff --git a/src/com/dre/brewery/listeners/PlayerListener.java b/src/com/dre/brewery/listeners/PlayerListener.java index da98716..05077b6 100644 --- a/src/com/dre/brewery/listeners/PlayerListener.java +++ b/src/com/dre/brewery/listeners/PlayerListener.java @@ -4,6 +4,7 @@ import com.dre.brewery.*; import com.dre.brewery.filedata.BConfig; import com.dre.brewery.filedata.UpdateChecker; import com.dre.brewery.utility.LegacyUtil; +import com.dre.brewery.utility.PermissionUtil; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.block.Block; @@ -256,6 +257,7 @@ public class PlayerListener implements Listener { if (bplayer != null) { bplayer.disconnecting(); } + PermissionUtil.logout(event.getPlayer()); } @EventHandler @@ -264,5 +266,6 @@ public class PlayerListener implements Listener { if (bplayer != null) { bplayer.disconnecting(); } + PermissionUtil.logout(event.getPlayer()); } } diff --git a/src/com/dre/brewery/listeners/TabListener.java b/src/com/dre/brewery/listeners/TabListener.java index 20d7e17..0ae0e54 100644 --- a/src/com/dre/brewery/listeners/TabListener.java +++ b/src/com/dre/brewery/listeners/TabListener.java @@ -1,47 +1,153 @@ package com.dre.brewery.listeners; +import com.dre.brewery.recipe.BRecipe; +import com.dre.brewery.utility.PermissionUtil; +import com.dre.brewery.utility.Tuple; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collection; +import java.util.HashSet; import java.util.List; -import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.dre.brewery.utility.PermissionUtil.BPermission.DRINK; +import static com.dre.brewery.utility.PermissionUtil.BPermission.WAKEUP; public class TabListener implements TabCompleter { - private static final Map> completions = new HashMap<>(); - private static final List topCompletions = new ArrayList<>(2); + private static final String[] COMPLETIONS = {"unLabel", "help"}; + private static final String[] EXT_COMPLETIONS = {"info", "create", "reload", "drink", "itemName", "seal", "static", "puke", "wakeup"}; - static { - completions.put("", Arrays.asList("info", "unlabel", "help")); - topCompletions.add("brew"); - //topCompletions.add("brewery"); - } + private static final String[] QUALITY = {"1", "10"}; + private static Set> mainSet; + private static Set> altSet; @Override - public List onTabComplete(CommandSender commandSender, Command cmd, String command, String[] args) { - if (args.length == 0) { - return topCompletions; - } else if (args.length == 1) { - for (Map.Entry> entry : completions.entrySet()) { - List list = new ArrayList<>(); - for (String comp : entry.getValue()) { - if (comp.startsWith(args[0])) { - list.add(comp); - } + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String command, String[] args) { + if (args.length < 1) { + return null; + } + if (args.length == 1) { + + List commands; + if (PermissionUtil.noExtendedPermissions(sender)) { + commands = filterWithInput(COMPLETIONS, args[0]); + } else { + Stream filteredCompletionsStream = Arrays.stream(COMPLETIONS) + .filter(s -> s.startsWith(args[0])); + Stream filteredExtendedCompletionsStream = Arrays.stream(EXT_COMPLETIONS) + .filter(s -> s.startsWith(args[0])); + + commands = Stream.concat(filteredCompletionsStream, filteredExtendedCompletionsStream) + .collect(Collectors.toList()); + } + if (commands.isEmpty()) { + return null; // Player List + } else { + return commands; + } + + } else if (args.length == 2) { + + if (args[0].equalsIgnoreCase("wakeup")) { + if (WAKEUP.checkCached(sender)) { + return tabWakeup(args[1]); } - if (list.isEmpty()) { - return null; - } - return list; + } + + } + + if (args[0].equalsIgnoreCase("create") || args[0].equalsIgnoreCase("drink")) { + if (DRINK.checkCached(sender)) { + return tabCreateAndDrink(args); } } + return null; } + + + private static final String[] WAK = {"list", "add", "check", "remove", "cancel"}; + public List tabWakeup(String input) { + return filterWithInput(WAK, input); + } + + public List tabCreateAndDrink(String[] args) { + if (args.length == 2) { + + if (mainSet == null) { + mainSet = new HashSet<>(); + altSet = new HashSet<>(); + for (BRecipe recipe : BRecipe.getAllRecipes()) { + mainSet.addAll(createLookupFromName(recipe.getName(5))); + + Set altNames = new HashSet<>(3); + altNames.add(recipe.getName(1)); + altNames.add(recipe.getName(10)); + if (recipe.getOptionalID().isPresent()) { + altNames.add(recipe.getOptionalID().get()); + } + + for (String altName : altNames) { + altSet.addAll(createLookupFromName(altName)); + } + + } + } + + final String input = args[1].toLowerCase(); + + List options = mainSet.stream() + .filter(s -> s.a().startsWith(input)) + .map(Tuple::second) + .collect(Collectors.toList()); + if (options.isEmpty()) { + options = altSet.stream() + .filter(s -> s.a().startsWith(input)) + .map(Tuple::second) + .collect(Collectors.toList()); + } + return options; + } else { + if (args[args.length - 2].matches("\\d")) { + // Player list + return null; + } else { + return filterWithInput(QUALITY, args[args.length - 1]); + } + } + + } + + private static List> createLookupFromName(final String name) { + return Arrays.stream(name.split(" ")) + .map(word -> new Tuple<>(word.toLowerCase(), name)) + .collect(Collectors.toList()); + } + + public static List filterWithInput(String[] options, String input) { + return Arrays.stream(options) + .filter(s -> s.startsWith(input)) + .collect(Collectors.toList()); + } + + public static List filterWithInput(Collection options, String input) { + return options.stream() + .filter(s -> s.startsWith(input)) + .collect(Collectors.toList()); + } + + public static void reload() { + mainSet = null; + altSet = null; + } } diff --git a/src/com/dre/brewery/recipe/BRecipe.java b/src/com/dre/brewery/recipe/BRecipe.java index 2259775..3d3d1e1 100644 --- a/src/com/dre/brewery/recipe/BRecipe.java +++ b/src/com/dre/brewery/recipe/BRecipe.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -416,13 +417,15 @@ public class BRecipe { } public void applyDrinkFeatures(Player player, int quality) { - if (playercmds != null && !playercmds.isEmpty()) { - for (String cmd : getPlayercmdsForQuality(quality)) { + List playerCmdsForQuality = getPlayercmdsForQuality(quality); + if (playerCmdsForQuality != null) { + for (String cmd : playerCmdsForQuality) { player.performCommand(BUtil.applyPlaceholders(cmd, player.getName(), quality)); } } - if (servercmds != null && !servercmds.isEmpty()) { - for (String cmd : getServercmdsForQuality(quality)) { + List serverCmdsForQuality = getServercmdsForQuality(quality); + if (serverCmdsForQuality != null) { + for (String cmd : serverCmdsForQuality) { P.p.getServer().dispatchCommand(P.p.getServer().getConsoleSender(), BUtil.applyPlaceholders(cmd, player.getName(), quality)); } } @@ -544,9 +547,8 @@ public class BRecipe { return false; } - @Nullable - public String getOptionalID() { - return optionalID; + public Optional getOptionalID() { + return Optional.ofNullable(optionalID); } public List getIngredients() { @@ -773,7 +775,7 @@ public class BRecipe { } } for (BRecipe recipe : recipes) { - if (recipe.getOptionalID().equalsIgnoreCase(name)) { + if (recipe.getOptionalID().isPresent() && recipe.getOptionalID().get().equalsIgnoreCase(name)) { return recipe; } } diff --git a/src/com/dre/brewery/utility/PermissionUtil.java b/src/com/dre/brewery/utility/PermissionUtil.java new file mode 100644 index 0000000..df4906b --- /dev/null +++ b/src/com/dre/brewery/utility/PermissionUtil.java @@ -0,0 +1,125 @@ +package com.dre.brewery.utility; + +import com.dre.brewery.P; +import org.bukkit.command.CommandSender; + +import java.util.HashMap; +import java.util.Map; + +public class PermissionUtil { + + public static Map extendedPermsCache = new HashMap<>(); + + public static void logout(CommandSender sender) { + extendedPermsCache.remove(sender); + } + + /** + * Update the Permission Cache, sets it to false if the sender + * currently doesn't have any more than the default permission + * + * @param sender The sender of which to update the permission cache + */ + public static void evaluateExtendedPermissions(CommandSender sender) { + for (BPermission perm : BPermission.values()) { + if (perm != BPermission.UNLABEL) { // This is the default permission + if (sender.hasPermission(perm.permission)) { + extendedPermsCache.put(sender, true); + return; + } + } + } + extendedPermsCache.put(sender, false); + } + + /** + * Check if the Sender might have more than just the default permissions + * + * @return false if there _might be_ more permissions for this sender + */ + public static boolean noExtendedPermissions(CommandSender sender) { + Boolean extendedPerms = extendedPermsCache.get(sender); + + if (extendedPerms == null) { + evaluateExtendedPermissions(sender); + extendedPerms = extendedPermsCache.get(sender); + } + P.p.log("extended Perms for " + sender.getName() + ": " + extendedPerms); + + return extendedPerms == null || !extendedPerms; + } + + /** + * Returns true if the Sender has the permission, returns false if the cache says he is unlikely to have it + * + * @return true only if the sender definitely has the permission. false if he hasn't or it's unlikely + */ + public static boolean hasCachedPermission(CommandSender sender, String permission) { + BPermission perm = BPermission.get(permission); + if (perm != null) { + return hasCachedPermission(sender, perm); + } else { + return sender.hasPermission(permission); + } + } + + /** + * Returns true if the Sender has the permission, returns false if the cache says he is unlikely to have it + * + * @return true only if the sender definitely has the permission. false if he hasn't or it's unlikely + */ + public static boolean hasCachedPermission(CommandSender sender, BPermission bPerm) { + if (bPerm != BPermission.UNLABEL) { + if (noExtendedPermissions(sender)) { + return false; + } + } + + return sender.hasPermission(bPerm.permission); + } + + + /** + * Brewery Permissions of _only_ the Commands + */ + public enum BPermission { + PLAYER("brewery.cmd.player"), + SEAL("brewery.cmd.seal"), + UNLABEL("brewery.cmd.unlabel"), + + INFO("brewery.cmd.info"), + INFO_OTHER("brewery.cmd.infoOther"), + + CREATE("brewery.cmd.create"), + DRINK("brewery.cmd.drink"), + DRINK_OTHER("brewery.cmd.drinkOther"), + + RELOAD("brewery.cmd.reload"), + PUKE("brewery.cmd.puke"), + PUKE_OTHER("brewery.cmd.pukeOther"), + WAKEUP("brewery.cmd.wakeup"), + + STATIC("brewery.cmd.static"), + COPY("brewery.cmd.copy"), + DELETE("brewery.cmd.delete"); + + public String permission; + + BPermission(String permission) { + this.permission = permission; + } + + public boolean checkCached(CommandSender sender) { + return hasCachedPermission(sender, this); + } + + public static BPermission get(String permission) { + for (BPermission bPerm : BPermission.values()) { + if (bPerm.permission.equals(permission)) { + return bPerm; + } + } + return null; + } + } +}