From 24f88338c8556d8fc555d1da672bad2836d3550d Mon Sep 17 00:00:00 2001 From: libraryaddict Date: Thu, 1 Dec 2016 06:38:43 +1300 Subject: [PATCH] Fixed bugs, added custom disguises support, create your own disguises --- disguises.yml | 7 + pom.xml | 3 +- .../disguise/DisguiseConfig.java | 72 ++ .../libraryaddict/disguise/LibsDisguises.java | 14 +- .../commands/DisguiseBaseCommand.java | 950 +-------------- .../commands/DisguiseCloneCommand.java | 4 +- .../disguise/commands/DisguiseCommand.java | 32 +- .../commands/DisguiseEntityCommand.java | 32 +- .../commands/DisguiseHelpCommand.java | 52 +- .../commands/DisguisePlayerCommand.java | 34 +- .../commands/DisguiseRadiusCommand.java | 35 +- .../disguise/disguisetypes/Disguise.java | 30 +- .../disguise/disguisetypes/FlagWatcher.java | 6 +- .../disguise/disguisetypes/LibsEquipment.java | 2 +- .../disguise/disguisetypes/MiscDisguise.java | 105 +- .../disguise/disguisetypes/MobDisguise.java | 102 +- .../disguisetypes/PlayerDisguise.java | 30 +- .../disguisetypes/TargetedDisguise.java | 4 + .../watchers/FallingBlockWatcher.java | 89 +- .../watchers/VillagerWatcher.java | 16 +- .../watchers/ZombieVillagerWatcher.java | 1 + .../disguise/utilities/DisguiseParser.java | 1043 +++++++++++++++++ .../disguise/utilities/LibsProfileLookup.java | 18 +- .../utilities/ReflectionFlagWatchers.java | 5 + .../disguise/utilities/ReflectionManager.java | 41 + 25 files changed, 1471 insertions(+), 1256 deletions(-) create mode 100644 disguises.yml create mode 100644 src/me/libraryaddict/disguise/utilities/DisguiseParser.java diff --git a/disguises.yml b/disguises.yml new file mode 100644 index 00000000..226c8022 --- /dev/null +++ b/disguises.yml @@ -0,0 +1,7 @@ +# Here you can create your own disguises and disguise into them using the normal disguise commands +# To create them is super simple, you're using it just like you would in a command. The only tricky thing is that it must be valid yaml. TIP: Enclose the strings in ' +# Please note that this is parsed exactly like a command, no spaces in your playername. +# The following disguises will work if you remove the '#' at the beginning of the line, this creates a disguise which you can use by /disguise libraryaddict. So simple! +Disguises: +# libraryaddict: 'player libraryaddict setArmor GOLD_BOOTS,GOLD_LEGGINGS,GOLD_CHESTPLATE,GOLD_HELMET setItemInMainHand WRITTEN_BOOK setGlowing setSkin {"id":"a149f81bf7844f8987c554afdd4db533","name":"libraryaddict","properties":[{"signature":"afoGOO45t3iGvTyQ732AlugPOvj13/RNjM0/utYlD4PZ4ab4Jopbzr8Px75+ALdkyegoKNcfaH4aXzylMvL6mIwaRdL0af7pfGibMMCMJ8F1RAMl2WqRslKBKXHGS1OXxMweoXW+RRatGgZsUC1BjxHMwd4RuXxrV9ZZ7x1r4xouUXmMzn19wqNO9EeG2q8AgF/hZdrnJPdTTrqJs04r4vCQiFiQsTWiY/B5CBOTh6fw4NpOHeeiJwHOLvN+6xKnAm77nKawaKCSciDwt54EeZoE/Q5ReQUEFgj++jdyHb5PJbhGytr//mazpTVzvlDnO06CZqigbiueV2/ush2gKSXQeimCXeNZzcj/CFgqAmMSEZQW3qHp+DgoqqtBNabJa0FBzpbQQ/jQWzoHfmUC/hTf0A0+hgOe4NqDc+xXYf4A9M/6/0JHz0voWhQJi8QriM699DeeUa31bVdTdKjcyK6Zw6/HIOJt++eFnkf++/zKt0fMiqfdRamSqR/K3w+Kk7cs2D345BNubl5L83YWmLbebUcAPKaza5gi17lUW+h/FitzfKAJZ+xsfSdj27nQLa24xYsyB3Fi5DcFLI2oQt5BYAvViT37sabGOXbDBsrijS4t3++mIbC+pCDiKi0hwZzvy0TPRTle2RMhJ6D66DmpykwqBOxzD73fEsieWX4=","name":"textures","value":"eyJ0aW1lc3RhbXAiOjE0ODA1MjA3NjAxNTksInByb2ZpbGVJZCI6ImExNDlmODFiZjc4NDRmODk4N2M1NTRhZmRkNGRiNTMzIiwicHJvZmlsZU5hbWUiOiJsaWJyYXJ5YWRkaWN0Iiwic2lnbmF0dXJlUmVxdWlyZWQiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS84ZTQ5NDVkMzZjZjVhNjI1OGZjOGY4ZTM5NmZlZWYzMzY1ZjM2MjgyYjE2MjY0OWI2M2NmZWQzNzNmNzY1OSJ9LCJDQVBFIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWZkNjFjM2M0YWM4OGYxYTM0NjhmYmRlZWY0NWNlYzg5ZTVhZmI4N2I5N2ExYTg0NWJmYjNjNjRmZDBiODgzIn19fQ=="}]}' +# Warrior: 'zombie setArmor DIAMOND_BOOTS,DIAMOND_LEGGINGS,DIAMOND_CHESTPLATE,DIAMOND_HELMET setItemInMainHand DIAMOND_SWORD setItemInOffHand SHIELD' \ No newline at end of file diff --git a/pom.xml b/pom.xml index f5824593..a7fbf478 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 LibsDisguises LibsDisguises - 9.1.1 + 9.1.1-SNAPSHOT src @@ -19,6 +19,7 @@ plugin.yml config.yml + disguises.yml README.md diff --git a/src/me/libraryaddict/disguise/DisguiseConfig.java b/src/me/libraryaddict/disguise/DisguiseConfig.java index c2918b74..3c6bab7c 100644 --- a/src/me/libraryaddict/disguise/DisguiseConfig.java +++ b/src/me/libraryaddict/disguise/DisguiseConfig.java @@ -1,8 +1,17 @@ package me.libraryaddict.disguise; +import java.io.File; +import java.util.HashMap; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.utilities.DisguiseParser; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguiseParseException; import me.libraryaddict.disguise.utilities.PacketsManager; public class DisguiseConfig { @@ -45,6 +54,7 @@ public class DisguiseConfig { private static String updateNotificationPermission; private static boolean viewSelfDisguise; private static boolean witherSkullEnabled; + private static HashMap customDisguises = new HashMap(); public static String getDisguiseBlownMessage() { return disguiseBlownMessage; @@ -109,6 +119,68 @@ public class DisguiseConfig { setStopShulkerDisguisesFromMoving(config.getBoolean("StopShulkerDisguisesFromMoving", true)); setHideDisguisedPlayers(config.getBoolean("HideDisguisedPlayersFromTab")); setShowDisguisedPlayersInTab(config.getBoolean("ShowPlayerDisguisesInTab")); + + customDisguises.clear(); + + File disguisesFile = new File("plugins/LibsDisguises/disguises.yml"); + + if (!disguisesFile.exists()) + return; + + YamlConfiguration disguisesConfig = YamlConfiguration.loadConfiguration(disguisesFile); + + ConfigurationSection section = disguisesConfig.getConfigurationSection("Disguises"); + + if (section == null) { + return; + } + + for (String key : section.getKeys(false)) { + String toParse = section.getString(key); + + if (getCustomDisguise(toParse) != null) { + System.err + .println("[LibsDisguises] Cannot create the custom disguise '" + key + "' as there is a name conflict!"); + continue; + } + + try { + Disguise disguise = DisguiseParser.parseDisguise(Bukkit.getConsoleSender(), "disguise", toParse.split(" "), + DisguiseParser.getPermissions(Bukkit.getConsoleSender(), "disguise")); + + customDisguises.put(key, disguise); + + System.out.println("[LibsDisguises] Loaded custom disguise " + key); + } + catch (DisguiseParseException e) { + System.err.println("[LibsDisguises] Error while loading custom disguise '" + key + "'" + + (e.getMessage() == null ? "" : ": " + e.getMessage())); + + if (e.getMessage() == null) + e.printStackTrace(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + System.out.println("[LibsDisguises] Loaded " + customDisguises.size() + " custom disguise" + + (customDisguises.size() == 1 ? "" : "s")); + } + + public static HashMap getCustomDisguises() { + return customDisguises; + } + + public static Entry getCustomDisguise(String disguise) { + for (Entry entry : customDisguises.entrySet()) { + if (!entry.getKey().equalsIgnoreCase(disguise) && !entry.getKey().replaceAll("_", "").equalsIgnoreCase(disguise)) + continue; + + return entry; + } + + return null; } public static boolean isAnimationPacketsEnabled() { diff --git a/src/me/libraryaddict/disguise/LibsDisguises.java b/src/me/libraryaddict/disguise/LibsDisguises.java index 544768ae..f339d551 100644 --- a/src/me/libraryaddict/disguise/LibsDisguises.java +++ b/src/me/libraryaddict/disguise/LibsDisguises.java @@ -1,5 +1,6 @@ package me.libraryaddict.disguise; +import java.io.File; import java.io.IOException; import java.lang.reflect.Field; @@ -81,13 +82,20 @@ public class LibsDisguises extends JavaPlugin { return; } + instance = this; + saveDefaultConfig(); + getLogger().info("Discovered MC version: " + ReflectionManager.getBukkitVersion()); - saveDefaultConfig(); + if (!new File(getDataFolder(), "disguises.yml").exists()) { + saveResource("disguises.yml", false); + } PacketsManager.init(this); DisguiseUtilities.init(this); + registerValues(); + DisguiseConfig.initConfig(getConfig()); PacketsManager.addPacketListeners(); @@ -109,10 +117,6 @@ public class LibsDisguises extends JavaPlugin { registerCommand("libsdisguises", new LibsDisguisesCommand()); registerCommand("disguiseviewself", new DisguiseViewSelfCommand()); - registerValues(); - - instance = this; - try { Metrics metrics = new Metrics(this); metrics.start(); diff --git a/src/me/libraryaddict/disguise/commands/DisguiseBaseCommand.java b/src/me/libraryaddict/disguise/commands/DisguiseBaseCommand.java index c409dd81..22d8b043 100644 --- a/src/me/libraryaddict/disguise/commands/DisguiseBaseCommand.java +++ b/src/me/libraryaddict/disguise/commands/DisguiseBaseCommand.java @@ -1,81 +1,21 @@ package me.libraryaddict.disguise.commands; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.regex.Pattern; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.BlockFace; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Ageable; -import org.bukkit.entity.Animals; -import org.bukkit.entity.Llama; -import org.bukkit.entity.Monster; -import org.bukkit.inventory.ItemStack; -import org.bukkit.permissions.PermissionAttachmentInfo; -import org.bukkit.potion.PotionEffectType; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.WrappedGameProfile; -import com.comphenix.protocol.wrappers.WrappedSignedProperty; -import com.google.gson.Gson; - -import me.libraryaddict.disguise.disguisetypes.AnimalColor; -import me.libraryaddict.disguise.disguisetypes.Disguise; -import me.libraryaddict.disguise.disguisetypes.DisguiseType; -import me.libraryaddict.disguise.disguisetypes.FlagWatcher; -import me.libraryaddict.disguise.disguisetypes.MiscDisguise; -import me.libraryaddict.disguise.disguisetypes.MobDisguise; -import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; -import me.libraryaddict.disguise.disguisetypes.RabbitType; -import me.libraryaddict.disguise.utilities.DisguiseUtilities; -import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers; +import me.libraryaddict.disguise.utilities.DisguiseParser; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; /** * @author libraryaddict */ public abstract class DisguiseBaseCommand implements CommandExecutor { - public class DisguiseParseException extends Exception { - private static final long serialVersionUID = 1276971370793124510L; - - public DisguiseParseException() { - super(); - } - - public DisguiseParseException(String string) { - super(string); - } - } - - private Object callValueOf(Class param, String valueString, String methodName, String description) - throws DisguiseParseException { - Object value; - try { - value = param.getMethod("valueOf", String.class).invoke(null, valueString.toUpperCase()); - } - catch (Exception ex) { - throw parseToException(description, valueString, methodName); - } - return value; - } - - private void doCheck(HashMap, Boolean> optionPermissions, ArrayList usedOptions) - throws DisguiseParseException { - - if (!passesCheck(optionPermissions, usedOptions)) { - throw new DisguiseParseException(ChatColor.RED + "You do not have the permission to use the option " - + usedOptions.get(usedOptions.size() - 1)); - } - } protected ArrayList filterTabs(ArrayList list, String[] origArgs) { if (origArgs.length == 0) @@ -93,14 +33,17 @@ public abstract class DisguiseBaseCommand implements CommandExecutor { itel.remove(); } - return list; + return new ArrayList(new HashSet(list)); } - protected ArrayList getAllowedDisguises(HashMap, Boolean>> hashMap) { + protected ArrayList getAllowedDisguises(HashMap, Boolean>> hashMap) { ArrayList allowedDisguises = new ArrayList<>(); - for (DisguiseType type : hashMap.keySet()) { - allowedDisguises.add(type.toReadable().replace(" ", "_")); + for (DisguisePerm type : hashMap.keySet()) { + if (type.isUnknown()) + continue; + + allowedDisguises.add(type.toReadable().replaceAll(" ", "_")); } Collections.sort(allowedDisguises, String.CASE_INSENSITIVE_ORDER); @@ -140,287 +83,8 @@ public abstract class DisguiseBaseCommand implements CommandExecutor { throw new UnsupportedOperationException("Unknown disguise command, perm node not found"); } - protected HashMap getDisguiseOptions(CommandSender sender, DisguiseType type) { - switch (type) { - case PLAYER: - case FALLING_BLOCK: - case PAINTING: - case SPLASH_POTION: - case FISHING_HOOK: - case DROPPED_ITEM: - HashMap returns = new HashMap<>(); - - String beginning = "libsdisguises.options." + getPermNode() + "."; - - for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) { - String lowerPerm = permission.getPermission().toLowerCase(); - - if (lowerPerm.startsWith(beginning)) { - String[] split = lowerPerm.substring(beginning.length()).split("\\."); - - if (split.length > 1) { - if (split[0].replace("_", "").equals(type.name().toLowerCase().replace("_", ""))) { - for (int i = 1; i < split.length; i++) { - returns.put(split[i], permission.getValue()); - } - } - } - } - } - - return returns; - default: - return new HashMap<>(); - } - } - - private Entry getMethod(Method[] methods, String methodName, int toStart) { - for (int i = toStart; i < methods.length; i++) { - Method method = methods[i]; - if (!method.getName().startsWith("get") && method.getName().equalsIgnoreCase(methodName) - && method.getAnnotation(Deprecated.class) == null && method.getParameterTypes().length == 1) { - return new HashMap.SimpleEntry(method, ++i); - } - } - return null; - } - - private HashMap, Boolean> getOptions(String perm) { - ArrayList list = new ArrayList<>(); - boolean isRemove = true; - String[] split = perm.split("\\."); - for (int i = 1; i < split.length; i++) { - String option = split[i]; - boolean value = option.startsWith("-"); - if (value) { - option = option.substring(1); - isRemove = false; - } - if (option.equals("baby")) { - option = "setbaby"; - } - list.add(option); - } - - HashMap, Boolean> options = new HashMap<>(); - options.put(list, isRemove); - - return options; - } - - protected HashMap, Boolean>> getPermissions(CommandSender sender) { - return getPermissions(sender, "libsdisguises." + getPermNode() + "."); - } - - /** - * Get perms for the node. Returns a hashmap of allowed disguisetypes and their options - * - * @param sender - * @param permissionNode - * @return - */ - protected HashMap, Boolean>> getPermissions(CommandSender sender, - String permissionNode) { - HashMap, Boolean>> singleDisguises = new HashMap<>(); - HashMap, Boolean>> rangeDisguises = new HashMap<>(); - HashMap perms = new HashMap<>(); - - for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) { - String perm = permission.getPermission().toLowerCase(); - - if (perm.startsWith(permissionNode) && (!perms.containsKey(perm) || !permission.getValue())) { - perms.put(perm, permission.getValue()); - } - } - - if (!perms.containsKey(permissionNode + "*") && sender.hasPermission(permissionNode + "*")) { - perms.put(permissionNode + "*", true); - } - - if (!perms.containsKey(permissionNode + "*.*") && sender.hasPermission(permissionNode + "*.*")) { - perms.put(permissionNode + "*.*", true); - } - - for (String perm : perms.keySet()) { - if (perms.get(perm)) { - perm = perm.substring(permissionNode.length()); - - String disguiseType = perm.split("\\.")[0]; - DisguiseType dType = null; - - for (DisguiseType t : DisguiseType.values()) { - if (t.name().replace("_", "").equalsIgnoreCase(disguiseType.replace("_", ""))) { - dType = t; - break; - } - } - - if (dType != null) { - HashMap, Boolean> list; - - if (singleDisguises.containsKey(dType)) { - list = singleDisguises.get(dType); - } - else { - list = new HashMap<>(); - singleDisguises.put(dType, list); - } - - HashMap, Boolean> map1 = getOptions(perm); - list.put(map1.keySet().iterator().next(), map1.values().iterator().next()); - } - else { - for (DisguiseType type : DisguiseType.values()) { - HashMap, Boolean> options = null; - Class entityClass = type.getEntityClass(); - - if (disguiseType.equals("mob")) { - if (type.isMob()) { - options = getOptions(perm); - } - } - else if (disguiseType.equals("animal") || disguiseType.equals("animals")) { - if (Animals.class.isAssignableFrom(entityClass)) { - options = getOptions(perm); - } - } - else if (disguiseType.equals("monster") || disguiseType.equals("monsters")) { - if (Monster.class.isAssignableFrom(entityClass)) { - options = getOptions(perm); - } - } - else if (disguiseType.equals("misc")) { - if (type.isMisc()) { - options = getOptions(perm); - } - } - else if (disguiseType.equals("ageable")) { - if (Ageable.class.isAssignableFrom(entityClass)) { - options = getOptions(perm); - } - } - else if (disguiseType.equals("*")) { - options = getOptions(perm); - } - - if (options != null) { - HashMap, Boolean> list; - - if (rangeDisguises.containsKey(type)) { - list = rangeDisguises.get(type); - } - else { - list = new HashMap<>(); - rangeDisguises.put(type, list); - } - - HashMap, Boolean> map1 = getOptions(perm); - - list.put(map1.keySet().iterator().next(), map1.values().iterator().next()); - } - } - } - } - } - - for (String perm : perms.keySet()) { - if (!perms.get(perm)) { - perm = perm.substring(permissionNode.length()); - - String disguiseType = perm.split("\\.")[0]; - DisguiseType dType = null; - - for (DisguiseType t : DisguiseType.values()) { - if (t.name().replace("_", "").equalsIgnoreCase(disguiseType.replace("_", ""))) { - dType = t; - break; - } - } - - if (dType != null) { - singleDisguises.remove(dType); - rangeDisguises.remove(dType); - } - else { - for (DisguiseType type : DisguiseType.values()) { - boolean foundHim = false; - Class entityClass = type.getEntityClass(); - - switch (disguiseType) { - case "mob": - if (type.isMob()) { - foundHim = true; - } - - break; - case "animal": - case "animals": - if (Animals.class.isAssignableFrom(entityClass)) { - foundHim = true; - } - - break; - case "monster": - case "monsters": - if (Monster.class.isAssignableFrom(entityClass)) { - foundHim = true; - } - - break; - case "misc": - if (type.isMisc()) { - foundHim = true; - } - - break; - case "ageable": - if (Ageable.class.isAssignableFrom(entityClass)) { - foundHim = true; - } - - break; - case "*": - foundHim = true; - break; - } - - if (foundHim) { - rangeDisguises.remove(type); - } - } - } - } - } - - HashMap, Boolean>> map = new HashMap<>(); - - for (DisguiseType type : DisguiseType.values()) { - HashMap, Boolean> temp = new HashMap<>(); - - if (singleDisguises.containsKey(type)) { - temp.putAll(singleDisguises.get(type)); - } - - if (rangeDisguises.containsKey(type)) { - temp.putAll(rangeDisguises.get(type)); - } - - if (!temp.isEmpty()) { - map.put(type, temp); - } - } - - return map; - } - - protected boolean isDouble(String string) { - try { - Float.parseFloat(string); - return true; - } - catch (Exception ex) { - return false; - } + protected HashMap, Boolean>> getPermissions(CommandSender sender) { + return DisguiseParser.getPermissions(sender, "libsdisguises." + getPermNode() + "."); } protected boolean isNumeric(String string) { @@ -433,594 +97,6 @@ public abstract class DisguiseBaseCommand implements CommandExecutor { } } - /** - * Returns the disguise if it all parsed correctly. Returns a exception with a complete message if it didn't. The - * commandsender is purely used for checking permissions. Would defeat the purpose otherwise. To reach this point, the - * disguise has been feed a proper disguisetype. - * - * @param sender - * @param args - * @param map - * @return - * @throws DisguiseBaseCommand.DisguiseParseException - * @throws java.lang.IllegalAccessException - * @throws java.lang.reflect.InvocationTargetException - */ - protected Disguise parseDisguise(CommandSender sender, String[] args, - HashMap, Boolean>> map) - throws DisguiseParseException, IllegalAccessException, InvocationTargetException { - if (map.isEmpty()) { - throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this command."); - } - - if (args.length == 0) { - sendCommandUsage(sender, map); - throw new DisguiseParseException(); - } - - // How many args to skip due to the disugise being constructed - // Time to start constructing the disguise. - // We will need to check between all 3 kinds of disguises - int toSkip = 1; - ArrayList usedOptions = new ArrayList<>(); - Disguise disguise = null; - HashMap, Boolean> optionPermissions; - - if (args[0].startsWith("@")) { - if (sender.hasPermission("libsdisguises.disguise.disguiseclone")) { - disguise = DisguiseUtilities.getClonedDisguise(args[0].toLowerCase()); - - if (disguise == null) { - throw new DisguiseParseException(ChatColor.RED + "Cannot find a disguise under the reference " + args[0]); - } - } - else { - throw new DisguiseParseException(ChatColor.RED + "You do not have perimssion to use disguise references!"); - } - - optionPermissions = (map.containsKey(disguise.getType()) ? map.get(disguise.getType()) - : new HashMap, Boolean>()); - } - else { - DisguiseType disguiseType = null; - - if (args[0].equalsIgnoreCase("p")) { - disguiseType = DisguiseType.PLAYER; - } - else { - for (DisguiseType type : DisguiseType.values()) { - if (args[0].equalsIgnoreCase(type.name()) || args[0].equalsIgnoreCase(type.name().replace("_", ""))) { - disguiseType = type; - break; - } - } - } - - if (disguiseType == null) { - throw new DisguiseParseException( - ChatColor.RED + "Error! The disguise " + ChatColor.GREEN + args[0] + ChatColor.RED + " doesn't exist!"); - } - - if (disguiseType.isUnknown()) { - throw new DisguiseParseException(ChatColor.RED + "Error! You cannot disguise as " + ChatColor.GREEN + "Unknown!"); - } - - if (disguiseType.getEntityType() == null) { - throw new DisguiseParseException(ChatColor.RED + "Error! This version of minecraft does not have that disguise!"); - } - - if (!map.containsKey(disguiseType)) { - throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this disguise."); - } - - optionPermissions = map.get(disguiseType); - - HashMap disguiseOptions = this.getDisguiseOptions(sender, disguiseType); - - if (disguiseType.isPlayer()) { - // If he is doing a player disguise - if (args.length == 1) { - // He needs to give the player name - throw new DisguiseParseException(ChatColor.RED + "Error! You need to give a player name!"); - } - else { - if (!disguiseOptions.isEmpty() && (!disguiseOptions.containsKey(args[1].toLowerCase()) - || !disguiseOptions.get(args[1].toLowerCase()))) { - throw new DisguiseParseException(ChatColor.RED + "Error! You don't have permission to use that name!"); - } - - args[1] = args[1].replace("\\_", " "); - - // Construct the player disguise - disguise = new PlayerDisguise(ChatColor.translateAlternateColorCodes('&', args[1])); - toSkip++; - } - } - else { - if (disguiseType.isMob()) { // Its a mob, use the mob constructor - boolean adult = true; - - if (args.length > 1) { - if (args[1].equalsIgnoreCase("baby") || args[1].equalsIgnoreCase("adult")) { - usedOptions.add("setbaby"); - doCheck(optionPermissions, usedOptions); - adult = args[1].equalsIgnoreCase("adult"); - - toSkip++; - } - } - - disguise = new MobDisguise(disguiseType, adult); - } - else if (disguiseType.isMisc()) { - // Its a misc, we are going to use the MiscDisguise constructor. - int miscId = -1; - int miscData = -1; - String secondArg = null; - - if (args.length > 1) { - // They have defined more arguments! - // If the first arg is a number - if (args[1].contains(":")) { - String[] split = args[1].split(":"); - if (isNumeric(split[1])) { - secondArg = split[1]; - } - args[1] = split[0]; - } - - if (isNumeric(args[1])) { - miscId = Integer.parseInt(args[1]); - } - else { - if (disguiseType == DisguiseType.FALLING_BLOCK || disguiseType == DisguiseType.DROPPED_ITEM) { - for (Material mat : Material.values()) { - if (mat.name().replace("_", "").equalsIgnoreCase(args[1].replace("_", ""))) { - miscId = mat.getId(); - break; - } - } - } - } - if (miscId != -1) { - switch (disguiseType) { - case PAINTING: - case FALLING_BLOCK: - case SPLASH_POTION: - case DROPPED_ITEM: - case FISHING_HOOK: - case ARROW: - case TIPPED_ARROW: - case SPECTRAL_ARROW: - case SMALL_FIREBALL: - case FIREBALL: - case WITHER_SKULL: - break; - default: - throw new DisguiseParseException(ChatColor.RED + "Error! " + disguiseType.toReadable() - + " doesn't know what to do with " + args[1] + "!"); - } - toSkip++; - // If they also defined a data value - if (args.length > 2 && secondArg == null && isNumeric(args[2])) { - secondArg = args[2]; - toSkip++; - } - if (secondArg != null) { - if (disguiseType != DisguiseType.FALLING_BLOCK && disguiseType != DisguiseType.DROPPED_ITEM) { - throw new DisguiseParseException(ChatColor.RED + "Error! Only the disguises " - + DisguiseType.FALLING_BLOCK.toReadable() + " and " - + DisguiseType.DROPPED_ITEM.toReadable() + " uses a second number!"); - } - miscData = Integer.parseInt(secondArg); - } - } - } - - if (!disguiseOptions.isEmpty() && miscId != -1) { - String toCheck = "" + miscId; - - if (miscData == 0 || miscData == -1) { - if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) { - toCheck += ":0"; - } - } - else { - toCheck += ":" + miscData; - } - - if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) { - throw new DisguiseParseException( - ChatColor.RED + "Error! You do not have permission to use the parameter " + toCheck - + " on the " + disguiseType.toReadable() + " disguise!"); - } - } - - if (miscId != -1) { - if (disguiseType == DisguiseType.FALLING_BLOCK) { - usedOptions.add("setblock"); - - doCheck(optionPermissions, usedOptions); - } - else if (disguiseType == DisguiseType.PAINTING) { - usedOptions.add("setpainting"); - - doCheck(optionPermissions, usedOptions); - } - else if (disguiseType == DisguiseType.SPLASH_POTION) { - usedOptions.add("setpotionid"); - - doCheck(optionPermissions, usedOptions); - } - } - // Construct the disguise - disguise = new MiscDisguise(disguiseType, miscId, miscData); - } - } - } - // Copy strings to their new range - String[] newArgs = new String[args.length - toSkip]; - System.arraycopy(args, toSkip, newArgs, 0, args.length - toSkip); - args = newArgs; - - Method[] methods = ReflectionFlagWatchers.getDisguiseWatcherMethods(disguise.getWatcher().getClass()); - - for (int i = 0; i < args.length; i += 2) { - String methodName = args[i]; - String valueString = (args.length - 1 == i ? null : args[i + 1]); - Method methodToUse = null; - Object value = null; - DisguiseParseException storedEx = null; - int c = 0; - - while (c < methods.length) { - try { - Entry entry = getMethod(methods, methodName, c); - - if (entry == null) { - break; - } - - methodToUse = entry.getKey(); - c = entry.getValue(); - methodName = methodToUse.getName(); - Class[] types = methodToUse.getParameterTypes(); - Class param = types[0]; - - if (valueString != null) { - if (int.class == param) { - // Parse to integer - if (isNumeric(valueString)) { - value = Integer.parseInt(valueString); - } - else { - throw parseToException("number", valueString, methodName); - } - } - else if (WrappedGameProfile.class == param && valueString.length() > 20) { - try { - Map response = new Gson().fromJson(valueString, Map.class); - - String id = (String) response.get("id"); - - if (!id.contains("-")) { - id = Pattern - .compile( - "([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)") - .matcher(id).replaceFirst("$1-$2-$3-$4-$5"); - } - - WrappedGameProfile gameProfile = new WrappedGameProfile(UUID.fromString(id), - (String) response.get("name")); - - if (response.containsKey("properties")) { - ArrayList> properties = (ArrayList) response.get("properties"); - - for (Map s : properties) { - String gName = null; - String gValue = null; - String gSigned = null; - - if (s.containsKey("name")) - gName = s.get("name"); - - if (s.containsKey("value")) - gValue = s.get("value"); - - if (s.containsKey("signature")) - gSigned = s.get("signature"); - - gameProfile.getProperties().put(gName, new WrappedSignedProperty(gName, gValue, gSigned)); - } - } - - value = gameProfile; - } - catch (Exception ex) { - throw parseToException("gameprofile", valueString, methodName); - } - } - else if (float.class == param || double.class == param) { - // Parse to number - if (isDouble(valueString)) { - float obj = Float.parseFloat(valueString); - if (param == float.class) { - value = obj; - } - else if (param == double.class) { - value = (double) obj; - } - } - else { - throw parseToException("number.0", valueString, methodName); - } - } - else if (param == String.class) { - if (methodName.equalsIgnoreCase("setskin") && valueString.length() > 20) - continue; - - // Parse to string - value = ChatColor.translateAlternateColorCodes('&', valueString); - } - else if (param == AnimalColor.class) { - // Parse to animal color - try { - value = AnimalColor.valueOf(valueString.toUpperCase()); - } - catch (Exception ex) { - throw parseToException("animal color", valueString, methodName); - } - } - else if (param == Llama.Color.class) { - try { - value = Llama.Color.valueOf(valueString.toUpperCase()); - } - catch (Exception ex) { - throw parseToException("llama color", valueString, methodName); - } - } - else if (param == ItemStack.class) { - // Parse to itemstack - try { - value = parseToItemstack(valueString); - } - catch (Exception ex) { - throw new DisguiseParseException(String.format(ex.getMessage(), methodName)); - } - } - else if (param == ItemStack[].class) { - // Parse to itemstack array - ItemStack[] items = new ItemStack[4]; - - String[] split = valueString.split(","); - - if (split.length == 4) { - for (int a = 0; a < 4; a++) { - try { - items[a] = parseToItemstack(split[a]); - } - catch (Exception ex) { - throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN - + "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName); - } - } - } - else { - throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN - + "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName); - } - - value = items; - } - else if (param.getSimpleName().equals("Color")) { - // Parse to horse color - value = callValueOf(param, valueString, methodName, "a horse color"); - } - else if (param.getSimpleName().equals("Style")) { - // Parse to horse style - value = callValueOf(param, valueString, methodName, "a horse style"); - } - else if (param.getSimpleName().equals("Profession")) { - // Parse to villager profession - value = callValueOf(param, valueString, methodName, "a villager profession"); - } - else if (param.getSimpleName().equals("Art")) { - // Parse to art type - value = callValueOf(param, valueString, methodName, "a painting art"); - } - else if (param.getSimpleName().equals("Type")) { - // Parse to ocelot type - value = callValueOf(param, valueString, methodName, "a ocelot type"); - } - else if (param == PotionEffectType.class) { - // Parse to potion effect - try { - PotionEffectType potionType = PotionEffectType.getByName(valueString.toUpperCase()); - if (potionType == null && isNumeric(valueString)) { - potionType = PotionEffectType.getById(Integer.parseInt(valueString)); - } - if (potionType == null) { - throw new DisguiseParseException(); - } - value = potionType; - } - catch (Exception ex) { - throw parseToException("a potioneffect type", valueString, methodName); - } - } - else if (param == int[].class) { - String[] split = valueString.split(","); - - int[] values = new int[split.length]; - - for (int b = 0; b < values.length; b++) { - try { - values[b] = Integer.parseInt(split[b]); - } - catch (NumberFormatException ex) { - throw parseToException("Number,Number,Number...", valueString, methodName); - } - } - - value = values; - } - else if (param == BlockFace.class) { - try { - BlockFace face = BlockFace.valueOf(valueString.toUpperCase()); - - if (face.ordinal() > 5) { - throw new DisguiseParseException(); - } - - value = face; - } - catch (Exception ex) { - throw parseToException("a direction (north, east, south, west, up, down)", valueString, - methodName); - } - } - else if (param == RabbitType.class) { - try { - for (RabbitType type : RabbitType.values()) { - if (type.name().replace("_", "") - .equalsIgnoreCase(valueString.replace("_", "").replace(" ", ""))) { - value = type; - - break; - } - } - if (value == null) { - throw new Exception(); - } - } - catch (Exception ex) { - throw parseToException("rabbit type (white, brown, patches...)", valueString, methodName); - } - } - else if (param == BlockPosition.class) { - try { - String[] split = valueString.split(","); - - assert split.length == 3; - - value = new BlockPosition(Integer.parseInt(split[0]), Integer.parseInt(split[1]), - Integer.parseInt(split[2])); - } - catch (Exception ex) { - throw parseToException("three numbers Number,Number,Number", valueString, methodName); - } - } - } - - if (value == null && boolean.class == param) { - if (valueString == null) { - value = true; - i--; - } - else if (valueString.equalsIgnoreCase("true")) { - value = true; - } - else if (valueString.equalsIgnoreCase("false")) { - value = false; - } - else { - if (getMethod(methods, valueString, 0) == null) { - throw parseToException("true/false", valueString, methodName); - } - else { - value = true; - i--; - } - } - } - - if (value != null) { - break; - } - } - catch (DisguiseParseException ex) { - storedEx = ex; - methodToUse = null; - } - catch (Exception ex) { - ex.printStackTrace(); - methodToUse = null; - } - } - if (methodToUse == null) { - if (storedEx != null) { - throw storedEx; - } - - throw new DisguiseParseException(ChatColor.RED + "Cannot find the option " + methodName); - } - if (value == null) { - throw new DisguiseParseException(ChatColor.RED + "No value was given for the option " + methodName); - } - - if (!usedOptions.contains(methodName.toLowerCase())) { - usedOptions.add(methodName.toLowerCase()); - } - - doCheck(optionPermissions, usedOptions); - - if (FlagWatcher.class.isAssignableFrom(methodToUse.getDeclaringClass())) { - methodToUse.invoke(disguise.getWatcher(), value); - } - else { - methodToUse.invoke(disguise, value); - } - } - // Alright. We've constructed our disguise. - return disguise; - } - - private DisguiseParseException parseToException(String expectedValue, String receivedInstead, String methodName) { - return new DisguiseParseException( - ChatColor.RED + "Expected " + ChatColor.GREEN + expectedValue + ChatColor.RED + ", received " + ChatColor.GREEN - + receivedInstead + ChatColor.RED + " instead for " + ChatColor.GREEN + methodName); - } - - private ItemStack parseToItemstack(String string) throws Exception { - String[] split = string.split(":", -1); - - int itemId = -1; - - if (isNumeric(split[0])) { - itemId = Integer.parseInt(split[0]); - } - else { - try { - itemId = Material.valueOf(split[0].toUpperCase()).getId(); - } - catch (Exception ex) { - } - } - - if (itemId != -1) { - short itemDura = 0; - - if (split.length > 1) { - if (isNumeric(split[1])) { - itemDura = Short.parseShort(split[1]); - } - else { - throw parseToException("item ID:Durability combo", string, "%s"); - } - } - - return new ItemStack(itemId, 1, itemDura); - } - else { - if (split.length == 1) { - throw parseToException("item ID", string, "%s"); - } - else { - throw parseToException("item ID:Durability combo", string, "%s"); - } - } - } - public boolean passesCheck(HashMap, Boolean> theirPermissions, ArrayList usedOptions) { boolean hasPermission = false; @@ -1043,5 +119,5 @@ public abstract class DisguiseBaseCommand implements CommandExecutor { } protected abstract void sendCommandUsage(CommandSender sender, - HashMap, Boolean>> map); + HashMap, Boolean>> map); } diff --git a/src/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java b/src/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java index 8ee3845a..7fcb7f1e 100644 --- a/src/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java +++ b/src/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java @@ -12,7 +12,7 @@ import org.bukkit.command.TabCompleter; import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.LibsDisguises; -import me.libraryaddict.disguise.disguisetypes.DisguiseType; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; public class DisguiseCloneCommand extends DisguiseBaseCommand implements TabCompleter { @Override @@ -79,7 +79,7 @@ public class DisguiseCloneCommand extends DisguiseBaseCommand implements TabComp * Send the player the information */ @Override - protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { + protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { sender.sendMessage(ChatColor.DARK_GREEN + "Right click a entity to get a disguise reference you can pass to other disguise commands!"); sender.sendMessage(ChatColor.DARK_GREEN diff --git a/src/me/libraryaddict/disguise/commands/DisguiseCommand.java b/src/me/libraryaddict/disguise/commands/DisguiseCommand.java index 50632868..e79167ee 100644 --- a/src/me/libraryaddict/disguise/commands/DisguiseCommand.java +++ b/src/me/libraryaddict/disguise/commands/DisguiseCommand.java @@ -18,6 +18,9 @@ import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; +import me.libraryaddict.disguise.utilities.DisguiseParser; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguiseParseException; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers.ParamInfo; @@ -29,10 +32,15 @@ public class DisguiseCommand extends DisguiseBaseCommand implements TabCompleter return true; } + if (args.length == 0) { + sendCommandUsage(sender, getPermissions(sender)); + return true; + } + Disguise disguise; try { - disguise = parseDisguise(sender, args, getPermissions(sender)); + disguise = DisguiseParser.parseDisguise(sender, getPermNode(), args, getPermissions(sender)); } catch (DisguiseParseException ex) { if (ex.getMessage() != null) { @@ -73,25 +81,21 @@ public class DisguiseCommand extends DisguiseBaseCommand implements TabCompleter ArrayList tabs = new ArrayList(); String[] args = getArgs(origArgs); - HashMap, Boolean>> perms = getPermissions(sender); + HashMap, Boolean>> perms = getPermissions(sender); if (args.length == 0) { - for (DisguiseType type : perms.keySet()) { - tabs.add(type.toReadable().replaceAll(" ", "_")); + for (String type : getAllowedDisguises(perms)) { + tabs.add(type); } } else { - DisguiseType disguiseType; + DisguisePerm disguiseType = DisguiseParser.getDisguisePerm(args[0]); - try { - disguiseType = DisguiseType.valueOf(args[0].toUpperCase()); - } - catch (Exception ex) { - // No disguisetype specificied, cannot help. + if (disguiseType == null) return filterTabs(tabs, origArgs); - } + // No disguisetype specificied, cannot help. - if (args.length == 1 && disguiseType == DisguiseType.PLAYER) { + if (args.length == 1 && disguiseType.getType() == DisguiseType.PLAYER) { for (Player player : Bukkit.getOnlinePlayers()) { tabs.add(player.getName()); } @@ -100,7 +104,7 @@ public class DisguiseCommand extends DisguiseBaseCommand implements TabCompleter ArrayList usedOptions = new ArrayList(); for (Method method : ReflectionFlagWatchers.getDisguiseWatcherMethods(disguiseType.getWatcherClass())) { - for (int i = disguiseType == DisguiseType.PLAYER ? 2 : 1; i < args.length; i++) { + for (int i = disguiseType.getType() == DisguiseType.PLAYER ? 2 : 1; i < args.length; i++) { String arg = args[i]; if (!method.getName().equalsIgnoreCase(arg)) @@ -154,7 +158,7 @@ public class DisguiseCommand extends DisguiseBaseCommand implements TabCompleter * Send the player the information */ @Override - protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { + protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { ArrayList allowedDisguises = getAllowedDisguises(map); sender.sendMessage(ChatColor.DARK_GREEN + "Choose a disguise to become the disguise!"); sender.sendMessage(ChatColor.DARK_GREEN + "You can use the disguises: " + ChatColor.GREEN diff --git a/src/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java b/src/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java index db505096..b70ffe74 100644 --- a/src/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java +++ b/src/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java @@ -18,6 +18,9 @@ import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; +import me.libraryaddict.disguise.utilities.DisguiseParser; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguiseParseException; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers.ParamInfo; @@ -29,10 +32,15 @@ public class DisguiseEntityCommand extends DisguiseBaseCommand implements TabCom return true; } + if (args.length == 0) { + sendCommandUsage(sender, getPermissions(sender)); + return true; + } + Disguise disguise; try { - disguise = parseDisguise(sender, args, getPermissions(sender)); + disguise = DisguiseParser.parseDisguise(sender, getPermNode(), args, getPermissions(sender)); } catch (DisguiseParseException ex) { if (ex.getMessage() != null) { @@ -58,25 +66,20 @@ public class DisguiseEntityCommand extends DisguiseBaseCommand implements TabCom ArrayList tabs = new ArrayList(); String[] args = getArgs(origArgs); - HashMap, Boolean>> perms = getPermissions(sender); + HashMap, Boolean>> perms = getPermissions(sender); if (args.length == 0) { - for (DisguiseType type : perms.keySet()) { - tabs.add(type.toReadable().replaceAll(" ", "_")); + for (String type : getAllowedDisguises(perms)) { + tabs.add(type); } } else { - DisguiseType disguiseType; + DisguisePerm disguiseType = DisguiseParser.getDisguisePerm(args[0]); - try { - disguiseType = DisguiseType.valueOf(args[0].toUpperCase()); - } - catch (Exception ex) { - // No disguisetype specificied, cannot help. + if (disguiseType == null) return filterTabs(tabs, origArgs); - } - if (args.length == 1 && disguiseType == DisguiseType.PLAYER) { + if (args.length == 1 && disguiseType.getType() == DisguiseType.PLAYER) { for (Player player : Bukkit.getOnlinePlayers()) { tabs.add(player.getName()); } @@ -85,7 +88,7 @@ public class DisguiseEntityCommand extends DisguiseBaseCommand implements TabCom ArrayList usedOptions = new ArrayList(); for (Method method : ReflectionFlagWatchers.getDisguiseWatcherMethods(disguiseType.getWatcherClass())) { - for (int i = disguiseType == DisguiseType.PLAYER ? 2 : 1; i < args.length; i++) { + for (int i = disguiseType.getType() == DisguiseType.PLAYER ? 2 : 1; i < args.length; i++) { String arg = args[i]; if (!method.getName().equalsIgnoreCase(arg)) @@ -142,8 +145,9 @@ public class DisguiseEntityCommand extends DisguiseBaseCommand implements TabCom * @param map */ @Override - protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { + protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { ArrayList allowedDisguises = getAllowedDisguises(map); + sender.sendMessage(ChatColor.DARK_GREEN + "Choose a disguise then right click a entity to disguise it!"); sender.sendMessage(ChatColor.DARK_GREEN + "You can use the disguises: " + ChatColor.GREEN + StringUtils.join(allowedDisguises, ChatColor.RED + ", " + ChatColor.GREEN)); diff --git a/src/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java b/src/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java index da4497e4..8f56c578 100644 --- a/src/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java +++ b/src/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java @@ -12,9 +12,10 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; -import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; +import me.libraryaddict.disguise.utilities.DisguiseParser; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers.ParamInfo; @@ -25,8 +26,9 @@ public class DisguiseHelpCommand extends DisguiseBaseCommand implements TabCompl for (String node : new String[] { "disguise", "disguiseradius", "disguiseentity", "disguiseplayer" }) { - HashMap, Boolean>> permMap = getPermissions(sender, + HashMap, Boolean>> permMap = DisguiseParser.getPermissions(sender, "libsdisguises." + node + "."); + if (!permMap.isEmpty()) { if (args.length == 0) { sendCommandUsage(sender, null); @@ -50,16 +52,7 @@ public class DisguiseHelpCommand extends DisguiseBaseCommand implements TabCompl return true; } - DisguiseType type = null; - - for (DisguiseType disguiseType : DisguiseType.values()) { - if (args[0].equalsIgnoreCase(disguiseType.name()) - || disguiseType.name().replace("_", "").equalsIgnoreCase(args[0])) { - - type = disguiseType; - break; - } - } + DisguisePerm type = DisguiseParser.getDisguisePerm(args[0]); if (type == null) { sender.sendMessage(ChatColor.RED + "Cannot find the disguise " + args[0]); @@ -143,8 +136,9 @@ public class DisguiseHelpCommand extends DisguiseBaseCommand implements TabCompl if (ignored > 0) { sender.sendMessage(ChatColor.RED + "Ignored " + ignored - + " options you do not have permission to view. Add 'show' to view unusable options."); + + " options you do not have permission to use. Add 'show' to view unusable options."); } + return true; } } @@ -159,25 +153,27 @@ public class DisguiseHelpCommand extends DisguiseBaseCommand implements TabCompl ArrayList tabs = new ArrayList(); String[] args = getArgs(origArgs); - HashMap, Boolean>> perms = getPermissions(sender); + for (String node : new String[] { + "disguise", "disguiseradius", "disguiseentity", "disguiseplayer" + }) { + HashMap, Boolean>> perms = DisguiseParser.getPermissions(sender, + "libsdisguises." + node + "."); - if (args.length == 0) { - for (DisguiseType type : perms.keySet()) { - tabs.add(type.toReadable().replaceAll(" ", "_")); - } + if (args.length == 0) { + for (DisguisePerm type : perms.keySet()) { + if (type.isUnknown()) + continue; - for (ParamInfo s : ReflectionFlagWatchers.getParamInfos()) { - tabs.add(s.getName().replaceAll(" ", "")); + tabs.add(type.toReadable().replaceAll(" ", "_")); + } + + for (ParamInfo s : ReflectionFlagWatchers.getParamInfos()) { + tabs.add(s.getName().replaceAll(" ", "")); + } } - } - else { - try { - DisguiseType.valueOf(args[0].toUpperCase()); - } - catch (Exception ex) { + else if (DisguiseParser.getDisguisePerm(args[0]) == null) { tabs.add("Show"); } - } return filterTabs(tabs, origArgs); @@ -187,7 +183,7 @@ public class DisguiseHelpCommand extends DisguiseBaseCommand implements TabCompl * Send the player the information */ @Override - protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { + protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { sender.sendMessage(ChatColor.RED + "/disguisehelp " + ChatColor.GREEN + "- View the options you can set on a disguise. Add 'show' to reveal the options you don't have permission to use"); diff --git a/src/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java b/src/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java index 035ee62a..7a288b7f 100644 --- a/src/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java +++ b/src/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java @@ -18,6 +18,9 @@ import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; +import me.libraryaddict.disguise.utilities.DisguiseParser; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguiseParseException; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers.ParamInfo; @@ -25,7 +28,7 @@ public class DisguisePlayerCommand extends DisguiseBaseCommand implements TabCom @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { - HashMap, Boolean>> map = getPermissions(sender); + HashMap, Boolean>> map = getPermissions(sender); if (map.isEmpty()) { sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); @@ -52,9 +55,15 @@ public class DisguisePlayerCommand extends DisguiseBaseCommand implements TabCom String[] newArgs = new String[args.length - 1]; System.arraycopy(args, 1, newArgs, 0, newArgs.length); + if (newArgs.length == 0) { + sendCommandUsage(sender, map); + return true; + } + Disguise disguise; + try { - disguise = parseDisguise(sender, newArgs, map); + disguise = DisguiseParser.parseDisguise(sender, getPermNode(), newArgs, map); } catch (DisguiseParseException ex) { if (ex.getMessage() != null) { @@ -104,7 +113,7 @@ public class DisguisePlayerCommand extends DisguiseBaseCommand implements TabCom ArrayList tabs = new ArrayList(); String[] args = getArgs(origArgs); - HashMap, Boolean>> perms = getPermissions(sender); + HashMap, Boolean>> perms = getPermissions(sender); if (args.length == 0) { for (Player player : Bukkit.getOnlinePlayers()) { @@ -112,22 +121,17 @@ public class DisguisePlayerCommand extends DisguiseBaseCommand implements TabCom } } else if (args.length == 1) { - for (DisguiseType type : perms.keySet()) { - tabs.add(type.toReadable().replaceAll(" ", "_")); + for (String type : getAllowedDisguises(perms)) { + tabs.add(type); } } else { - DisguiseType disguiseType; + DisguisePerm disguiseType = DisguiseParser.getDisguisePerm(args[1]); - try { - disguiseType = DisguiseType.valueOf(args[1].toUpperCase()); - } - catch (Exception ex) { - // No disguisetype specificied, cannot help. + if (disguiseType == null) return filterTabs(tabs, origArgs); - } - if (args.length == 2 && disguiseType == DisguiseType.PLAYER) { + if (args.length == 2 && disguiseType.getType() == DisguiseType.PLAYER) { for (Player player : Bukkit.getOnlinePlayers()) { tabs.add(player.getName()); } @@ -136,7 +140,7 @@ public class DisguisePlayerCommand extends DisguiseBaseCommand implements TabCom ArrayList usedOptions = new ArrayList(); for (Method method : ReflectionFlagWatchers.getDisguiseWatcherMethods(disguiseType.getWatcherClass())) { - for (int i = disguiseType == DisguiseType.PLAYER ? 3 : 2; i < args.length; i++) { + for (int i = disguiseType.getType() == DisguiseType.PLAYER ? 3 : 2; i < args.length; i++) { String arg = args[i]; if (!method.getName().equalsIgnoreCase(arg)) @@ -190,7 +194,7 @@ public class DisguisePlayerCommand extends DisguiseBaseCommand implements TabCom * Send the player the information */ @Override - protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { + protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { ArrayList allowedDisguises = getAllowedDisguises(map); sender.sendMessage(ChatColor.DARK_GREEN + "Disguise another player!"); diff --git a/src/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java b/src/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java index ba270e77..1f903d1c 100644 --- a/src/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java +++ b/src/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java @@ -23,6 +23,9 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; import me.libraryaddict.disguise.utilities.ClassGetter; +import me.libraryaddict.disguise.utilities.DisguiseParser; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguiseParseException; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers; import me.libraryaddict.disguise.utilities.ReflectionFlagWatchers.ParamInfo; @@ -46,7 +49,7 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom return true; } - HashMap, Boolean>> map = getPermissions(sender); + HashMap, Boolean>> map = getPermissions(sender); if (map.isEmpty()) { sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); @@ -125,8 +128,13 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom System.arraycopy(args, starting + 1, newArgs, 0, newArgs.length); Disguise disguise; + if (newArgs.length == 0) { + sendCommandUsage(sender, map); + return true; + } + try { - disguise = parseDisguise(sender, newArgs, map); + disguise = DisguiseParser.parseDisguise(sender, getPermNode(), newArgs, map); } catch (DisguiseParseException ex) { if (ex.getMessage() != null) { @@ -195,7 +203,7 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom ArrayList tabs = new ArrayList(); String[] args = getArgs(origArgs); - HashMap, Boolean>> perms = getPermissions(sender); + HashMap, Boolean>> perms = getPermissions(sender); if (args.length == 0) { for (Class entityClass : validClasses) { @@ -222,22 +230,18 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom } if (args.length == starting) { - for (DisguiseType type : perms.keySet()) { - tabs.add(type.toReadable().replaceAll(" ", "_")); + for (String type : getAllowedDisguises(perms)) { + tabs.add(type); } } else { - DisguiseType disguiseType; - try { - disguiseType = DisguiseType.valueOf(args[starting].toUpperCase()); - } - catch (Exception ex) { - // No disguisetype specificied, cannot help. + DisguisePerm disguiseType = DisguiseParser.getDisguisePerm(args[starting]); + + if (disguiseType == null) return filterTabs(tabs, origArgs); - } - if (args.length == 1 + starting && disguiseType == DisguiseType.PLAYER) { + if (args.length == 1 + starting && disguiseType.getType() == DisguiseType.PLAYER) { for (Player player : Bukkit.getOnlinePlayers()) { tabs.add(player.getName()); } @@ -246,7 +250,8 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom ArrayList usedOptions = new ArrayList(); for (Method method : ReflectionFlagWatchers.getDisguiseWatcherMethods(disguiseType.getWatcherClass())) { - for (int i = disguiseType == DisguiseType.PLAYER ? starting + 2 : starting + 1; i < args.length; i++) { + for (int i = disguiseType.getType() == DisguiseType.PLAYER ? starting + 2 + : starting + 1; i < args.length; i++) { String arg = args[i]; if (!method.getName().equalsIgnoreCase(arg)) @@ -300,7 +305,7 @@ public class DisguiseRadiusCommand extends DisguiseBaseCommand implements TabCom * Send the player the information */ @Override - protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { + protected void sendCommandUsage(CommandSender sender, HashMap, Boolean>> map) { ArrayList allowedDisguises = getAllowedDisguises(map); sender.sendMessage(ChatColor.DARK_GREEN + "Disguise all entities in a radius! Caps at " + maxRadius + " blocks!"); diff --git a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java index 0850e24d..f8392fbf 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -71,6 +71,10 @@ public abstract class Disguise { private boolean viewSelfDisguise = DisguiseConfig.isViewDisguises(); private FlagWatcher watcher; + public Disguise(DisguiseType disguiseType) { + this.disguiseType = disguiseType; + } + @Override public abstract Disguise clone(); @@ -80,18 +84,12 @@ public abstract class Disguise { * @param newType * The disguise */ - protected void createDisguise(DisguiseType newType) { - if (getWatcher() != null) { - return; - } - - if (newType.getEntityType() == null) { - throw new RuntimeException("DisguiseType " + newType + protected void createDisguise() { + if (getType().getEntityType() == null) { + throw new RuntimeException("DisguiseType " + getType() + " was used in a futile attempt to construct a disguise, but this Minecraft version does not have that entity"); } - // Set the disguise type - disguiseType = newType; // Get if they are a adult now.. boolean isAdult = true; @@ -100,12 +98,14 @@ public abstract class Disguise { isAdult = ((MobDisguise) this).isAdult(); } - try { - // Construct the FlagWatcher from the stored class - setWatcher((FlagWatcher) getType().getWatcherClass().getConstructor(Disguise.class).newInstance(this)); - } - catch (Exception e) { - e.printStackTrace(); + if (getWatcher() == null) { + try { + // Construct the FlagWatcher from the stored class + setWatcher((FlagWatcher) getType().getWatcherClass().getConstructor(Disguise.class).newInstance(this)); + } + catch (Exception e) { + e.printStackTrace(); + } } // Set the disguise if its a baby or not diff --git a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java index 9430b5b3..c3670516 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java @@ -47,7 +47,7 @@ public class FlagWatcher { private byte addEntityAnimations(byte originalValue, byte entityValue) { for (int i = 0; i < 6; i++) { - if ((entityValue & 1 << i) != 0 && !modifiedEntityAnimations[i]) { + if ((entityValue & 1 << i) != 0 && !modifiedEntityAnimations[i - 1]) { originalValue = (byte) (originalValue | 1 << i); } } @@ -401,7 +401,7 @@ public class FlagWatcher { } private void setEntityFlag(int byteValue, boolean flag) { - modifiedEntityAnimations[byteValue] = true; + modifiedEntityAnimations[byteValue - 1] = true; byte b0 = (byte) getData(FlagType.ENTITY_META); @@ -447,7 +447,7 @@ public class FlagWatcher { } public void setItemStack(EquipmentSlot slot, ItemStack itemStack) { - setItemStack(slot, itemStack); + equipment.setItem(slot, itemStack); sendItemStack(slot, itemStack); } diff --git a/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java b/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java index 5824c584..262c6864 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java +++ b/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java @@ -6,7 +6,7 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; public class LibsEquipment implements EntityEquipment { - private ItemStack[] equipment = new ItemStack[6]; + private ItemStack[] equipment = new ItemStack[EquipmentSlot.values().length]; private FlagWatcher flagWatcher; public LibsEquipment(FlagWatcher flagWatcher) { diff --git a/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java index d472c777..ef72388f 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java @@ -12,33 +12,31 @@ import me.libraryaddict.disguise.disguisetypes.watchers.FallingBlockWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.PaintingWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SplashPotionWatcher; -public class MiscDisguise extends TargetedDisguise -{ +public class MiscDisguise extends TargetedDisguise { private int id = -1, data = 0; - public MiscDisguise(DisguiseType disguiseType) - { + public MiscDisguise(DisguiseType disguiseType) { this(disguiseType, -1, disguiseType.getDefaultData()); } - public MiscDisguise(DisguiseType disguiseType, int id) - { + public MiscDisguise(DisguiseType disguiseType, int id) { this(disguiseType, id, disguiseType.getDefaultData()); } - public MiscDisguise(DisguiseType disguiseType, int id, int data) - { - if (!disguiseType.isMisc()) - { + public MiscDisguise(DisguiseType disguiseType, int id, int data) { + super(disguiseType); + + if (!disguiseType.isMisc()) { throw new InvalidParameterException("Expected a non-living DisguiseType while constructing MiscDisguise. Received " + disguiseType + " instead. Please use " + (disguiseType.isPlayer() ? "PlayerDisguise" : "MobDisguise") + " instead"); } - createDisguise(disguiseType); + + createDisguise(); + this.id = getType().getTypeId(); this.data = getType().getDefaultData(); - switch (disguiseType) - { + switch (disguiseType) { // The only disguises which should use a custom data. case PAINTING: ((PaintingWatcher) getWatcher()).setArt(Art.values()[Math.max(0, id) % Art.values().length]); @@ -51,8 +49,7 @@ public class MiscDisguise extends TargetedDisguise break; case DROPPED_ITEM: - if (id > 0) - { + if (id > 0) { ((DroppedItemWatcher) getWatcher()).setItemStack(new ItemStack(id, Math.max(1, data))); } break; @@ -71,20 +68,17 @@ public class MiscDisguise extends TargetedDisguise } @Override - public MiscDisguise addPlayer(Player player) - { + public MiscDisguise addPlayer(Player player) { return (MiscDisguise) super.addPlayer(player); } @Override - public MiscDisguise addPlayer(String playername) - { + public MiscDisguise addPlayer(String playername) { return (MiscDisguise) super.addPlayer(playername); } @Override - public MiscDisguise clone() - { + public MiscDisguise clone() { MiscDisguise disguise = new MiscDisguise(getType(), getData()); disguise.setReplaceSounds(isSoundsReplaced()); disguise.setViewSelfDisguise(isSelfDisguiseVisible()); @@ -94,8 +88,7 @@ public class MiscDisguise extends TargetedDisguise disguise.setVelocitySent(isVelocitySent()); disguise.setModifyBoundingBox(isModifyBoundingBox()); - if (getWatcher() != null) - { + if (getWatcher() != null) { disguise.setWatcher(getWatcher().clone(disguise)); } return disguise; @@ -104,10 +97,8 @@ public class MiscDisguise extends TargetedDisguise /** * This is the getId of everything but falling block. */ - public int getData() - { - switch (getType()) - { + public int getData() { + switch (getType()) { case FALLING_BLOCK: return (int) ((FallingBlockWatcher) getWatcher()).getBlock().getDurability(); case PAINTING: @@ -122,120 +113,100 @@ public class MiscDisguise extends TargetedDisguise /** * Only falling block should use this */ - public int getId() - { - if (getType() == DisguiseType.FALLING_BLOCK) - { + public int getId() { + if (getType() == DisguiseType.FALLING_BLOCK) { return ((FallingBlockWatcher) getWatcher()).getBlock().getTypeId(); } return id; } @Override - public boolean isMiscDisguise() - { + public boolean isMiscDisguise() { return true; } @Override - public MiscDisguise removePlayer(Player player) - { + public MiscDisguise removePlayer(Player player) { return (MiscDisguise) super.removePlayer(player); } @Override - public MiscDisguise removePlayer(String playername) - { + public MiscDisguise removePlayer(String playername) { return (MiscDisguise) super.removePlayer(playername); } @Override - public MiscDisguise setDisguiseTarget(TargetType newTargetType) - { + public MiscDisguise setDisguiseTarget(TargetType newTargetType) { return (MiscDisguise) super.setDisguiseTarget(newTargetType); } @Override - public MiscDisguise setEntity(Entity entity) - { + public MiscDisguise setEntity(Entity entity) { return (MiscDisguise) super.setEntity(entity); } @Override - public MiscDisguise setHearSelfDisguise(boolean hearSelfDisguise) - { + public MiscDisguise setHearSelfDisguise(boolean hearSelfDisguise) { return (MiscDisguise) super.setHearSelfDisguise(hearSelfDisguise); } @Override - public MiscDisguise setHideArmorFromSelf(boolean hideArmor) - { + public MiscDisguise setHideArmorFromSelf(boolean hideArmor) { return (MiscDisguise) super.setHideArmorFromSelf(hideArmor); } @Override - public MiscDisguise setHideHeldItemFromSelf(boolean hideHeldItem) - { + public MiscDisguise setHideHeldItemFromSelf(boolean hideHeldItem) { return (MiscDisguise) super.setHideHeldItemFromSelf(hideHeldItem); } @Override - public MiscDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) - { + public MiscDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) { return (MiscDisguise) super.setKeepDisguiseOnEntityDespawn(keepDisguise); } @Override - public MiscDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) - { + public MiscDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) { return (MiscDisguise) super.setKeepDisguiseOnPlayerDeath(keepDisguise); } @Override - public MiscDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) - { + public MiscDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) { return (MiscDisguise) super.setKeepDisguiseOnPlayerLogout(keepDisguise); } @Override - public MiscDisguise setModifyBoundingBox(boolean modifyBox) - { + public MiscDisguise setModifyBoundingBox(boolean modifyBox) { return (MiscDisguise) super.setModifyBoundingBox(modifyBox); } @Override - public MiscDisguise setReplaceSounds(boolean areSoundsReplaced) - { + public MiscDisguise setReplaceSounds(boolean areSoundsReplaced) { return (MiscDisguise) super.setReplaceSounds(areSoundsReplaced); } @Override - public MiscDisguise setVelocitySent(boolean sendVelocity) - { + public MiscDisguise setVelocitySent(boolean sendVelocity) { return (MiscDisguise) super.setVelocitySent(sendVelocity); } @Override - public MiscDisguise setViewSelfDisguise(boolean viewSelfDisguise) - { + public MiscDisguise setViewSelfDisguise(boolean viewSelfDisguise) { return (MiscDisguise) super.setViewSelfDisguise(viewSelfDisguise); } @Override - public MiscDisguise setWatcher(FlagWatcher newWatcher) - { + public MiscDisguise setWatcher(FlagWatcher newWatcher) { return (MiscDisguise) super.setWatcher(newWatcher); } @Override - public MiscDisguise silentlyAddPlayer(String playername) - { + public MiscDisguise silentlyAddPlayer(String playername) { return (MiscDisguise) super.silentlyAddPlayer(playername); } @Override - public MiscDisguise silentlyRemovePlayer(String playername) - { + public MiscDisguise silentlyRemovePlayer(String playername) { return (MiscDisguise) super.silentlyRemovePlayer(playername); } diff --git a/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java index 5b609495..07d2e146 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java @@ -9,43 +9,38 @@ import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; -public class MobDisguise extends TargetedDisguise -{ - +public class MobDisguise extends TargetedDisguise { private boolean isAdult; - public MobDisguise(DisguiseType disguiseType) - { + public MobDisguise(DisguiseType disguiseType) { this(disguiseType, true); } - public MobDisguise(DisguiseType disguiseType, boolean isAdult) - { - if (!disguiseType.isMob()) - { + public MobDisguise(DisguiseType disguiseType, boolean isAdult) { + super(disguiseType); + + if (!disguiseType.isMob()) { throw new InvalidParameterException("Expected a living DisguiseType while constructing MobDisguise. Received " + disguiseType + " instead. Please use " + (disguiseType.isPlayer() ? "PlayerDisguise" : "MiscDisguise") + " instead"); } + this.isAdult = isAdult; - createDisguise(disguiseType); + createDisguise(); } @Override - public MobDisguise addPlayer(Player player) - { + public MobDisguise addPlayer(Player player) { return (MobDisguise) super.addPlayer(player); } @Override - public MobDisguise addPlayer(String playername) - { + public MobDisguise addPlayer(String playername) { return (MobDisguise) super.addPlayer(playername); } @Override - public MobDisguise clone() - { + public MobDisguise clone() { MobDisguise disguise = new MobDisguise(getType(), isAdult()); disguise.setReplaceSounds(isSoundsReplaced()); disguise.setViewSelfDisguise(isSelfDisguiseVisible()); @@ -55,35 +50,28 @@ public class MobDisguise extends TargetedDisguise disguise.setVelocitySent(isVelocitySent()); disguise.setModifyBoundingBox(isModifyBoundingBox()); - if (getWatcher() != null) - { + if (getWatcher() != null) { disguise.setWatcher(getWatcher().clone(disguise)); } return disguise; } - public boolean doesDisguiseAge() - { + public boolean doesDisguiseAge() { return getWatcher() != null && (getWatcher() instanceof AgeableWatcher || getWatcher() instanceof ZombieWatcher); } @Override - public LivingWatcher getWatcher() - { + public LivingWatcher getWatcher() { return (LivingWatcher) super.getWatcher(); } - public boolean isAdult() - { - if (getWatcher() != null) - { - if (getWatcher() instanceof AgeableWatcher) - { + public boolean isAdult() { + if (getWatcher() != null) { + if (getWatcher() instanceof AgeableWatcher) { return ((AgeableWatcher) getWatcher()).isAdult(); } - else if (getWatcher() instanceof ZombieWatcher) - { + else if (getWatcher() instanceof ZombieWatcher) { return ((ZombieWatcher) getWatcher()).isAdult(); } return true; @@ -92,110 +80,92 @@ public class MobDisguise extends TargetedDisguise } @Override - public boolean isMobDisguise() - { + public boolean isMobDisguise() { return true; } @Override - public MobDisguise removePlayer(Player player) - { + public MobDisguise removePlayer(Player player) { return (MobDisguise) super.removePlayer(player); } @Override - public MobDisguise removePlayer(String playername) - { + public MobDisguise removePlayer(String playername) { return (MobDisguise) super.removePlayer(playername); } @Override - public MobDisguise setDisguiseTarget(TargetType newTargetType) - { + public MobDisguise setDisguiseTarget(TargetType newTargetType) { return (MobDisguise) super.setDisguiseTarget(newTargetType); } @Override - public MobDisguise setEntity(Entity entity) - { + public MobDisguise setEntity(Entity entity) { return (MobDisguise) super.setEntity(entity); } @Override - public MobDisguise setHearSelfDisguise(boolean hearSelfDisguise) - { + public MobDisguise setHearSelfDisguise(boolean hearSelfDisguise) { return (MobDisguise) super.setHearSelfDisguise(hearSelfDisguise); } @Override - public MobDisguise setHideArmorFromSelf(boolean hideArmor) - { + public MobDisguise setHideArmorFromSelf(boolean hideArmor) { return (MobDisguise) super.setHideArmorFromSelf(hideArmor); } @Override - public MobDisguise setHideHeldItemFromSelf(boolean hideHeldItem) - { + public MobDisguise setHideHeldItemFromSelf(boolean hideHeldItem) { return (MobDisguise) super.setHideHeldItemFromSelf(hideHeldItem); } @Override - public MobDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) - { + public MobDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) { return (MobDisguise) super.setKeepDisguiseOnEntityDespawn(keepDisguise); } @Override - public MobDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) - { + public MobDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) { return (MobDisguise) super.setKeepDisguiseOnPlayerDeath(keepDisguise); } @Override - public MobDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) - { + public MobDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) { return (MobDisguise) super.setKeepDisguiseOnPlayerLogout(keepDisguise); } @Override - public MobDisguise setModifyBoundingBox(boolean modifyBox) - { + public MobDisguise setModifyBoundingBox(boolean modifyBox) { return (MobDisguise) super.setModifyBoundingBox(modifyBox); } @Override - public MobDisguise setReplaceSounds(boolean areSoundsReplaced) - { + public MobDisguise setReplaceSounds(boolean areSoundsReplaced) { return (MobDisguise) super.setReplaceSounds(areSoundsReplaced); } @Override - public MobDisguise setVelocitySent(boolean sendVelocity) - { + public MobDisguise setVelocitySent(boolean sendVelocity) { return (MobDisguise) super.setVelocitySent(sendVelocity); } @Override - public MobDisguise setViewSelfDisguise(boolean viewSelfDisguise) - { + public MobDisguise setViewSelfDisguise(boolean viewSelfDisguise) { return (MobDisguise) super.setViewSelfDisguise(viewSelfDisguise); } @Override - public MobDisguise setWatcher(FlagWatcher newWatcher) - { + public MobDisguise setWatcher(FlagWatcher newWatcher) { return (MobDisguise) super.setWatcher(newWatcher); } @Override - public MobDisguise silentlyAddPlayer(String playername) - { + public MobDisguise silentlyAddPlayer(String playername) { return (MobDisguise) super.silentlyAddPlayer(playername); } @Override - public MobDisguise silentlyRemovePlayer(String playername) - { + public MobDisguise silentlyRemovePlayer(String playername) { return (MobDisguise) super.silentlyRemovePlayer(playername); } } diff --git a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java index 7fbfc948..38cd1405 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java @@ -32,7 +32,7 @@ public class PlayerDisguise extends TargetedDisguise { private UUID uuid = UUID.randomUUID(); private PlayerDisguise() { - // Internal usage only + super(DisguiseType.PLAYER); } public PlayerDisguise(Player player) { @@ -44,35 +44,43 @@ public class PlayerDisguise extends TargetedDisguise { } public PlayerDisguise(String name) { + this(); + setName(name); setSkin(name); - createDisguise(DisguiseType.PLAYER); + createDisguise(); } public PlayerDisguise(String name, String skinToUse) { + this(); + setName(name); setSkin(skinToUse); - createDisguise(DisguiseType.PLAYER); + createDisguise(); } public PlayerDisguise(WrappedGameProfile gameProfile) { + this(); + setName(gameProfile.getName()); this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(uuid, gameProfile.getName(), gameProfile); - createDisguise(DisguiseType.PLAYER); + createDisguise(); } public PlayerDisguise(WrappedGameProfile gameProfile, WrappedGameProfile skinToUse) { + this(); + setName(gameProfile.getName()); this.gameProfile = ReflectionManager.getGameProfile(uuid, gameProfile.getName()); setSkin(skinToUse); - createDisguise(DisguiseType.PLAYER); + createDisguise(); } @Override @@ -112,7 +120,7 @@ public class PlayerDisguise extends TargetedDisguise { disguise.setWatcher(getWatcher().clone(disguise)); } - disguise.createDisguise(DisguiseType.PLAYER); + disguise.createDisguise(); return disguise; } @@ -230,6 +238,16 @@ public class PlayerDisguise extends TargetedDisguise { } public PlayerDisguise setSkin(String newSkin) { + if (newSkin != null && newSkin.length() > 50) { + try { + setSkin(ReflectionManager.parseGameProfile(newSkin)); + } + catch (Exception ex) { + throw new IllegalArgumentException( + "The skin is too long to be a playername, but cannot be parsed to a GameProfile!"); + } + } + skinToUse = newSkin; if (newSkin == null) { diff --git a/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java index f45a050a..ce4ea22c 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java @@ -23,6 +23,10 @@ import me.libraryaddict.disguise.utilities.ReflectionManager; public abstract class TargetedDisguise extends Disguise { + public TargetedDisguise(DisguiseType disguiseType) { + super(disguiseType); + } + public enum TargetType { HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS, SHOW_TO_EVERYONE_BUT_THESE_PLAYERS } diff --git a/src/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java index a5fd6d74..0f31630b 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java @@ -1,48 +1,41 @@ -package me.libraryaddict.disguise.disguisetypes.watchers; - -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; - -import me.libraryaddict.disguise.DisguiseAPI; -import me.libraryaddict.disguise.disguisetypes.Disguise; -import me.libraryaddict.disguise.disguisetypes.FlagWatcher; -import me.libraryaddict.disguise.utilities.DisguiseUtilities; - -public class FallingBlockWatcher extends FlagWatcher -{ - private ItemStack block; - - public FallingBlockWatcher(Disguise disguise) - { - super(disguise); - } - - @Override - public FallingBlockWatcher clone(Disguise disguise) - { - FallingBlockWatcher watcher = (FallingBlockWatcher) super.clone(disguise); - watcher.setBlock(getBlock()); - - return watcher; - } - - public ItemStack getBlock() - { - return block; - } - - public void setBlock(ItemStack block) - { - this.block = block; - - if (block.getType() == null || block.getType() == Material.AIR) - { - block.setType(Material.STONE); - } - - if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) - { - DisguiseUtilities.refreshTrackers(getDisguise()); - } - } -} +package me.libraryaddict.disguise.disguisetypes.watchers; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.FlagWatcher; +import me.libraryaddict.disguise.utilities.DisguiseUtilities; + +public class FallingBlockWatcher extends FlagWatcher { + private ItemStack block; + + public FallingBlockWatcher(Disguise disguise) { + super(disguise); + } + + @Override + public FallingBlockWatcher clone(Disguise disguise) { + FallingBlockWatcher watcher = (FallingBlockWatcher) super.clone(disguise); + watcher.setBlock(getBlock()); + + return watcher; + } + + public ItemStack getBlock() { + return block; + } + + public void setBlock(ItemStack block) { + this.block = block; + + if (block == null || block.getType() == null || block.getType() == Material.AIR) { + block.setType(Material.STONE); + } + + if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) { + DisguiseUtilities.refreshTrackers(getDisguise()); + } + } +} diff --git a/src/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java index 3c51941c..1a94de0a 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java @@ -6,28 +6,24 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.FlagType; import me.libraryaddict.disguise.utilities.DisguiseUtilities; -public class VillagerWatcher extends AgeableWatcher -{ +public class VillagerWatcher extends AgeableWatcher { - public VillagerWatcher(Disguise disguise) - { + public VillagerWatcher(Disguise disguise) { super(disguise); setProfession(Profession.values()[DisguiseUtilities.random.nextInt(Profession.values().length)]); } - public Profession getProfession() - { + public Profession getProfession() { return Profession.values()[getData(FlagType.VILLAGER_PROFESSION)]; } - public void setProfession(int professionId) - { + @Deprecated + public void setProfession(int professionId) { setData(FlagType.VILLAGER_PROFESSION, professionId); sendData(FlagType.VILLAGER_PROFESSION); } - public void setProfession(Profession newProfession) - { + public void setProfession(Profession newProfession) { setProfession(newProfession.ordinal()); } } diff --git a/src/me/libraryaddict/disguise/disguisetypes/watchers/ZombieVillagerWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/watchers/ZombieVillagerWatcher.java index dbbee79b..0ea140b0 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/watchers/ZombieVillagerWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/watchers/ZombieVillagerWatcher.java @@ -43,6 +43,7 @@ public class ZombieVillagerWatcher extends ZombieWatcher { * * @param id */ + @Deprecated public void setProfession(int id) { setData(FlagType.ZOMBIE_VILLAGER_PROFESSION, id); sendData(FlagType.ZOMBIE_VILLAGER_PROFESSION); diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseParser.java b/src/me/libraryaddict/disguise/utilities/DisguiseParser.java new file mode 100644 index 00000000..cb29af09 --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/DisguiseParser.java @@ -0,0 +1,1043 @@ +package me.libraryaddict.disguise.utilities; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map.Entry; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Ageable; +import org.bukkit.entity.Animals; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Llama; +import org.bukkit.entity.Monster; +import org.bukkit.inventory.ItemStack; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.potion.PotionEffectType; + +import com.comphenix.protocol.wrappers.BlockPosition; +import com.comphenix.protocol.wrappers.WrappedGameProfile; + +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.commands.DisguiseBaseCommand; +import me.libraryaddict.disguise.disguisetypes.AnimalColor; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.DisguiseType; +import me.libraryaddict.disguise.disguisetypes.FlagWatcher; +import me.libraryaddict.disguise.disguisetypes.MiscDisguise; +import me.libraryaddict.disguise.disguisetypes.MobDisguise; +import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; +import me.libraryaddict.disguise.disguisetypes.RabbitType; + +public class DisguiseParser { + public static class DisguiseParseException extends Exception { + private static final long serialVersionUID = 1276971370793124510L; + + public DisguiseParseException() { + super(); + } + + public DisguiseParseException(String string) { + super(string); + } + } + + public static class DisguisePerm { + private DisguiseType disguiseType; + private String permName; + + public DisguisePerm(DisguiseType disguiseType) { + this.disguiseType = disguiseType; + } + + public DisguisePerm(DisguiseType disguiseType, String disguisePerm) { + this.disguiseType = disguiseType; + permName = disguisePerm; + } + + public Class getEntityClass() { + return getType().getEntityClass(); + } + + public EntityType getEntityType() { + return getType().getEntityType(); + } + + public DisguiseType getType() { + return disguiseType; + } + + public Class getWatcherClass() { + return getType().getWatcherClass(); + } + + public boolean isMisc() { + return getType().isMisc(); + } + + public boolean isMob() { + return getType().isMob(); + } + + public boolean isPlayer() { + return getType().isPlayer(); + } + + public boolean isUnknown() { + return getType().isUnknown(); + } + + public String name() { + return permName == null ? getType().name() : permName; + } + + public String toReadable() { + return permName == null ? getType().toReadable() : permName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((disguiseType == null) ? 0 : disguiseType.hashCode()); + result = prime * result + ((permName == null) ? 0 : permName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null) + return false; + + if (!(obj instanceof DisguisePerm)) + return false; + + DisguisePerm other = (DisguisePerm) obj; + + if (disguiseType != other.disguiseType) + return false; + + if (permName == null) { + if (other.permName != null) + return false; + } + + else if (!permName.equals(other.permName)) + return false; + + return true; + } + } + + private static Object callValueOf(Class param, String valueString, String methodName, String description) + throws DisguiseParseException { + Object value; + try { + value = param.getMethod("valueOf", String.class).invoke(null, valueString.toUpperCase()); + } + catch (Exception ex) { + throw parseToException(description, valueString, methodName); + } + return value; + } + + private static void doCheck(HashMap, Boolean> optionPermissions, ArrayList usedOptions) + throws DisguiseParseException { + + if (!passesCheck(optionPermissions, usedOptions)) { + throw new DisguiseParseException(ChatColor.RED + "You do not have the permission to use the option " + + usedOptions.get(usedOptions.size() - 1)); + } + } + + private static HashMap getDisguiseOptions(CommandSender sender, String permNode, DisguisePerm type) { + switch (type.getType()) { + case PLAYER: + case FALLING_BLOCK: + case PAINTING: + case SPLASH_POTION: + case FISHING_HOOK: + case DROPPED_ITEM: + HashMap returns = new HashMap<>(); + + String beginning = "libsdisguises.options." + permNode + "."; + + for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) { + String lowerPerm = permission.getPermission().toLowerCase(); + + if (lowerPerm.startsWith(beginning)) { + String[] split = lowerPerm.substring(beginning.length()).split("\\."); + + if (split.length > 1) { + if (split[0].replace("_", "").equals(type.name().toLowerCase().replace("_", ""))) { + for (int i = 1; i < split.length; i++) { + returns.put(split[i], permission.getValue()); + } + } + } + } + } + + return returns; + default: + return new HashMap<>(); + } + } + + public static DisguisePerm getDisguisePerm(String name) { + for (DisguisePerm perm : getDisguisePerms()) { + if (!perm.name().equalsIgnoreCase(name) && !perm.name().replace("_", "").equalsIgnoreCase(name)) + continue; + + return perm; + } + + return null; + } + + public static DisguisePerm[] getDisguisePerms() { + DisguisePerm[] perms = new DisguisePerm[DisguiseType.values().length + DisguiseConfig.getCustomDisguises().size()]; + int i = 0; + + for (DisguiseType disguiseType : DisguiseType.values()) { + perms[i++] = new DisguisePerm(disguiseType); + } + + for (Entry entry : DisguiseConfig.getCustomDisguises().entrySet()) { + perms[i++] = new DisguisePerm(entry.getValue().getType(), entry.getKey()); + } + + return perms; + } + + private static Entry getMethod(Method[] methods, String methodName, int toStart) { + for (int i = toStart; i < methods.length; i++) { + Method method = methods[i]; + + if (!method.getName().equalsIgnoreCase(methodName)) + continue; + + return new HashMap.SimpleEntry(method, ++i); + } + return null; + } + + private static HashMap, Boolean> getOptions(String perm) { + ArrayList list = new ArrayList<>(); + boolean isRemove = true; + String[] split = perm.split("\\."); + + for (int i = 1; i < split.length; i++) { + String option = split[i]; + boolean value = option.startsWith("-"); + + if (value) { + option = option.substring(1); + isRemove = false; + } + + if (option.equals("baby")) { + option = "setbaby"; + } + + list.add(option); + } + + HashMap, Boolean> options = new HashMap<>(); + options.put(list, isRemove); + + return options; + } + + /** + * Get perms for the node. Returns a hashmap of allowed disguisetypes and their options + * + * @param sender + * @param permissionNode + * @return + */ + public static HashMap, Boolean>> getPermissions(CommandSender sender, + String permissionNode) { + HashMap, Boolean>> singleDisguises = new HashMap<>(); + HashMap, Boolean>> rangeDisguises = new HashMap<>(); + HashMap perms = new HashMap<>(); + + for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) { + String perm = permission.getPermission().toLowerCase(); + + if (perm.startsWith(permissionNode) && (!perms.containsKey(perm) || !permission.getValue())) { + perms.put(perm, permission.getValue()); + } + } + + if (!perms.containsKey(permissionNode + "*") && sender.hasPermission(permissionNode + "*")) { + perms.put(permissionNode + "*", true); + } + + if (!perms.containsKey(permissionNode + "*.*") && sender.hasPermission(permissionNode + "*.*")) { + perms.put(permissionNode + "*.*", true); + } + + for (String perm : perms.keySet()) { + if (perms.get(perm)) { + perm = perm.substring(permissionNode.length()); + + String disguiseType = perm.split("\\.")[0]; + DisguisePerm dPerm = DisguiseParser.getDisguisePerm(disguiseType); + + if (dPerm != null) { + HashMap, Boolean> list; + + if (singleDisguises.containsKey(dPerm)) { + list = singleDisguises.get(dPerm); + } + else { + list = new HashMap<>(); + singleDisguises.put(dPerm, list); + } + + HashMap, Boolean> map1 = getOptions(perm); + list.put(map1.keySet().iterator().next(), map1.values().iterator().next()); + } + else { + for (DisguisePerm type : getDisguisePerms()) { + HashMap, Boolean> options = null; + Class entityClass = type.getEntityClass(); + + if (disguiseType.equals("mob")) { + if (type.isMob()) { + options = getOptions(perm); + } + } + else if (disguiseType.equals("animal") || disguiseType.equals("animals")) { + if (Animals.class.isAssignableFrom(entityClass)) { + options = getOptions(perm); + } + } + else if (disguiseType.equals("monster") || disguiseType.equals("monsters")) { + if (Monster.class.isAssignableFrom(entityClass)) { + options = getOptions(perm); + } + } + else if (disguiseType.equals("misc")) { + if (type.isMisc()) { + options = getOptions(perm); + } + } + else if (disguiseType.equals("ageable")) { + if (Ageable.class.isAssignableFrom(entityClass)) { + options = getOptions(perm); + } + } + else if (disguiseType.equals("*")) { + options = getOptions(perm); + } + + if (options != null) { + HashMap, Boolean> list; + + if (rangeDisguises.containsKey(type)) { + list = rangeDisguises.get(type); + } + else { + list = new HashMap<>(); + rangeDisguises.put(type, list); + } + + HashMap, Boolean> map1 = getOptions(perm); + + list.put(map1.keySet().iterator().next(), map1.values().iterator().next()); + } + } + } + } + } + + for (String perm : perms.keySet()) { + if (!perms.get(perm)) { + perm = perm.substring(permissionNode.length()); + + String disguiseType = perm.split("\\.")[0]; + DisguisePerm dType = DisguiseParser.getDisguisePerm(disguiseType); + + if (dType != null) { + singleDisguises.remove(dType); + rangeDisguises.remove(dType); + } + else { + for (DisguisePerm type : getDisguisePerms()) { + boolean foundHim = false; + Class entityClass = type.getEntityClass(); + + switch (disguiseType) { + case "mob": + if (type.isMob()) { + foundHim = true; + } + + break; + case "animal": + case "animals": + if (Animals.class.isAssignableFrom(entityClass)) { + foundHim = true; + } + + break; + case "monster": + case "monsters": + if (Monster.class.isAssignableFrom(entityClass)) { + foundHim = true; + } + + break; + case "misc": + if (type.isMisc()) { + foundHim = true; + } + + break; + case "ageable": + if (Ageable.class.isAssignableFrom(entityClass)) { + foundHim = true; + } + + break; + case "*": + foundHim = true; + break; + } + + if (foundHim) { + rangeDisguises.remove(type); + } + } + } + } + } + + HashMap, Boolean>> map = new HashMap<>(); + + for (DisguisePerm type : getDisguisePerms()) { + HashMap, Boolean> temp = new HashMap<>(); + + if (singleDisguises.containsKey(type)) { + temp.putAll(singleDisguises.get(type)); + } + + if (rangeDisguises.containsKey(type)) { + temp.putAll(rangeDisguises.get(type)); + } + + if (!temp.isEmpty()) { + map.put(type, temp); + } + } + + return map; + } + + private static boolean isDouble(String string) { + try { + Float.parseFloat(string); + return true; + } + catch (Exception ex) { + return false; + } + } + + private static boolean isNumeric(String string) { + try { + Integer.parseInt(string); + return true; + } + catch (Exception ex) { + return false; + } + } + + /** + * Returns the disguise if it all parsed correctly. Returns a exception with a complete message if it didn't. The + * commandsender is purely used for checking permissions. Would defeat the purpose otherwise. To reach this point, the + * disguise has been feed a proper disguisetype. + * + * @param sender + * @param args + * @param permissionMap + * @return + * @throws DisguiseBaseCommand.DisguiseParseException + * @throws java.lang.IllegalAccessException + * @throws java.lang.reflect.InvocationTargetException + */ + public static Disguise parseDisguise(CommandSender sender, String permNode, String[] args, + HashMap, Boolean>> permissionMap) + throws DisguiseParseException, IllegalAccessException, InvocationTargetException { + if (permissionMap.isEmpty()) { + throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this command."); + } + + if (args.length == 0) { + throw new DisguiseParseException("No arguments defined"); + } + + // How many args to skip due to the disugise being constructed + // Time to start constructing the disguise. + // We will need to check between all 3 kinds of disguises + int toSkip = 1; + ArrayList usedOptions = new ArrayList<>(); + Disguise disguise = null; + HashMap, Boolean> optionPermissions; + + if (args[0].startsWith("@")) { + if (sender.hasPermission("libsdisguises.disguise.disguiseclone")) { + disguise = DisguiseUtilities.getClonedDisguise(args[0].toLowerCase()); + + if (disguise == null) { + throw new DisguiseParseException(ChatColor.RED + "Cannot find a disguise under the reference " + args[0]); + } + } + else { + throw new DisguiseParseException(ChatColor.RED + "You do not have perimssion to use disguise references!"); + } + + optionPermissions = (permissionMap.containsKey(disguise.getType()) ? permissionMap.get(disguise.getType()) + : new HashMap, Boolean>()); + } + else { + DisguisePerm disguisePerm = getDisguisePerm(args[0]); + Entry customDisguise = DisguiseConfig.getCustomDisguise(args[0]); + + if (customDisguise != null) { + disguise = customDisguise.getValue().clone(); + } + else if (args[0].equalsIgnoreCase("p")) { + disguisePerm = new DisguisePerm(DisguiseType.PLAYER); + } + + if (disguisePerm == null) { + throw new DisguiseParseException( + ChatColor.RED + "Error! The disguise " + ChatColor.GREEN + args[0] + ChatColor.RED + " doesn't exist!"); + } + + if (disguisePerm.isUnknown()) { + throw new DisguiseParseException(ChatColor.RED + "Error! You cannot disguise as " + ChatColor.GREEN + "Unknown!"); + } + + if (disguisePerm.getEntityType() == null) { + throw new DisguiseParseException(ChatColor.RED + "Error! This disguise couldn't be loaded!"); + } + + if (!permissionMap.containsKey(disguisePerm)) { + throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this disguise."); + } + + optionPermissions = permissionMap.get(disguisePerm); + + HashMap disguiseOptions = getDisguiseOptions(sender, permNode, disguisePerm); + + if (disguise == null) { + if (disguisePerm.isPlayer()) { + // If he is doing a player disguise + if (args.length == 1) { + // He needs to give the player name + throw new DisguiseParseException(ChatColor.RED + "Error! You need to give a player name!"); + } + else { + if (!disguiseOptions.isEmpty() && (!disguiseOptions.containsKey(args[1].toLowerCase()) + || !disguiseOptions.get(args[1].toLowerCase()))) { + throw new DisguiseParseException( + ChatColor.RED + "Error! You don't have permission to use that name!"); + } + + args[1] = args[1].replace("\\_", " "); + + // Construct the player disguise + disguise = new PlayerDisguise(ChatColor.translateAlternateColorCodes('&', args[1])); + toSkip++; + } + } + else if (disguisePerm.isMob()) { // Its a mob, use the mob constructor + boolean adult = true; + + if (args.length > 1) { + if (args[1].equalsIgnoreCase("baby") || args[1].equalsIgnoreCase("adult")) { + usedOptions.add("setbaby"); + doCheck(optionPermissions, usedOptions); + adult = args[1].equalsIgnoreCase("adult"); + + toSkip++; + } + } + + disguise = new MobDisguise(disguisePerm.getType(), adult); + } + else if (disguisePerm.isMisc()) { + // Its a misc, we are going to use the MiscDisguise constructor. + int miscId = -1; + int miscData = -1; + String secondArg = null; + + if (args.length > 1) { + // They have defined more arguments! + // If the first arg is a number + if (args[1].contains(":")) { + String[] split = args[1].split(":"); + if (isNumeric(split[1])) { + secondArg = split[1]; + } + args[1] = split[0]; + } + + if (isNumeric(args[1])) { + miscId = Integer.parseInt(args[1]); + } + else { + if (disguisePerm.getType() == DisguiseType.FALLING_BLOCK + || disguisePerm.getType() == DisguiseType.DROPPED_ITEM) { + for (Material mat : Material.values()) { + if (mat.name().replace("_", "").equalsIgnoreCase(args[1].replace("_", ""))) { + miscId = mat.getId(); + break; + } + } + } + } + if (miscId != -1) { + switch (disguisePerm.getType()) { + case PAINTING: + case FALLING_BLOCK: + case SPLASH_POTION: + case DROPPED_ITEM: + case FISHING_HOOK: + case ARROW: + case TIPPED_ARROW: + case SPECTRAL_ARROW: + case SMALL_FIREBALL: + case FIREBALL: + case WITHER_SKULL: + break; + default: + throw new DisguiseParseException(ChatColor.RED + "Error! " + disguisePerm.toReadable() + + " doesn't know what to do with " + args[1] + "!"); + } + toSkip++; + // If they also defined a data value + if (args.length > 2 && secondArg == null && isNumeric(args[2])) { + secondArg = args[2]; + toSkip++; + } + if (secondArg != null) { + if (disguisePerm.getType() != DisguiseType.FALLING_BLOCK + && disguisePerm.getType() != DisguiseType.DROPPED_ITEM) { + throw new DisguiseParseException(ChatColor.RED + "Error! Only the disguises " + + DisguiseType.FALLING_BLOCK.toReadable() + " and " + + DisguiseType.DROPPED_ITEM.toReadable() + " uses a second number!"); + } + miscData = Integer.parseInt(secondArg); + } + } + } + + if (!disguiseOptions.isEmpty() && miscId != -1) { + String toCheck = "" + miscId; + + if (miscData == 0 || miscData == -1) { + if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) { + toCheck += ":0"; + } + } + else { + toCheck += ":" + miscData; + } + + if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) { + throw new DisguiseParseException( + ChatColor.RED + "Error! You do not have permission to use the parameter " + toCheck + + " on the " + disguisePerm.toReadable() + " disguise!"); + } + } + + if (miscId != -1) { + if (disguisePerm.getType() == DisguiseType.FALLING_BLOCK) { + usedOptions.add("setblock"); + + doCheck(optionPermissions, usedOptions); + } + else if (disguisePerm.getType() == DisguiseType.PAINTING) { + usedOptions.add("setpainting"); + + doCheck(optionPermissions, usedOptions); + } + else if (disguisePerm.getType() == DisguiseType.SPLASH_POTION) { + usedOptions.add("setpotionid"); + + doCheck(optionPermissions, usedOptions); + } + } + // Construct the disguise + disguise = new MiscDisguise(disguisePerm.getType(), miscId, miscData); + } + } + } + + // Copy strings to their new range + String[] newArgs = new String[args.length - toSkip]; + System.arraycopy(args, toSkip, newArgs, 0, args.length - toSkip); + args = newArgs; + + Method[] methods = ReflectionFlagWatchers.getDisguiseWatcherMethods(disguise.getWatcher().getClass()); + + for (int i = 0; i < args.length; i += 2) { + String methodName = args[i]; + String valueString = (args.length - 1 == i ? null : args[i + 1]); + Method methodToUse = null; + Object value = null; + DisguiseParseException storedEx = null; + int c = 0; + + while (c < methods.length) { + try { + Entry entry = getMethod(methods, methodName, c); + + if (entry == null) { + break; + } + + methodToUse = entry.getKey(); + c = entry.getValue(); + methodName = methodToUse.getName(); + Class[] types = methodToUse.getParameterTypes(); + Class param = types[0]; + + if (valueString != null) { + if (int.class == param) { + // Parse to integer + if (isNumeric(valueString)) { + value = Integer.parseInt(valueString); + } + else { + throw parseToException("number", valueString, methodName); + } + } + else if (WrappedGameProfile.class == param && valueString.length() > 20) { + try { + value = ReflectionManager.parseGameProfile(valueString); + } + catch (Exception ex) { + throw parseToException("gameprofile", valueString, methodName); + } + } + else if (float.class == param || double.class == param) { + // Parse to number + if (isDouble(valueString)) { + float obj = Float.parseFloat(valueString); + if (param == float.class) { + value = obj; + } + else if (param == double.class) { + value = (double) obj; + } + } + else { + throw parseToException("number.0", valueString, methodName); + } + } + else if (param == String.class) { + if (methodName.equalsIgnoreCase("setskin") && valueString.length() > 20) { + value = valueString; + } + else { + // Parse to string + value = ChatColor.translateAlternateColorCodes('&', valueString); + } + } + else if (param == AnimalColor.class) { + // Parse to animal color + try { + value = AnimalColor.valueOf(valueString.toUpperCase()); + } + catch (Exception ex) { + throw parseToException("animal color", valueString, methodName); + } + } + else if (param == Llama.Color.class) { + try { + value = Llama.Color.valueOf(valueString.toUpperCase()); + } + catch (Exception ex) { + throw parseToException("llama color", valueString, methodName); + } + } + else if (param == ItemStack.class) { + // Parse to itemstack + try { + value = parseToItemstack(valueString); + } + catch (Exception ex) { + throw new DisguiseParseException(String.format(ex.getMessage(), methodName)); + } + } + else if (param == ItemStack[].class) { + // Parse to itemstack array + ItemStack[] items = new ItemStack[4]; + + String[] split = valueString.split(","); + + if (split.length == 4) { + for (int a = 0; a < 4; a++) { + try { + items[a] = parseToItemstack(split[a]); + } + catch (Exception ex) { + throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN + + "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName); + } + } + } + else { + throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN + + "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName); + } + + value = items; + } + else if (param.getSimpleName().equals("Color")) { + // Parse to horse color + value = callValueOf(param, valueString, methodName, "a horse color"); + } + else if (param.getSimpleName().equals("Style")) { + // Parse to horse style + value = callValueOf(param, valueString, methodName, "a horse style"); + } + else if (param.getSimpleName().equals("Profession")) { + // Parse to villager profession + value = callValueOf(param, valueString, methodName, "a villager profession"); + } + else if (param.getSimpleName().equals("Art")) { + // Parse to art type + value = callValueOf(param, valueString, methodName, "a painting art"); + } + else if (param.getSimpleName().equals("Type")) { + // Parse to ocelot type + value = callValueOf(param, valueString, methodName, "a ocelot type"); + } + else if (param == PotionEffectType.class) { + // Parse to potion effect + try { + PotionEffectType potionType = PotionEffectType.getByName(valueString.toUpperCase()); + if (potionType == null && isNumeric(valueString)) { + potionType = PotionEffectType.getById(Integer.parseInt(valueString)); + } + + if (potionType == null) { + throw new DisguiseParseException(); + } + + value = potionType; + } + catch (Exception ex) { + throw parseToException("a potioneffect type", valueString, methodName); + } + } + else if (param == int[].class) { + String[] split = valueString.split(","); + + int[] values = new int[split.length]; + + for (int b = 0; b < values.length; b++) { + try { + values[b] = Integer.parseInt(split[b]); + } + catch (NumberFormatException ex) { + throw parseToException("Number,Number,Number...", valueString, methodName); + } + } + + value = values; + } + else if (param == BlockFace.class) { + try { + BlockFace face = BlockFace.valueOf(valueString.toUpperCase()); + + if (face.ordinal() > 5) { + throw new DisguiseParseException(); + } + + value = face; + } + catch (Exception ex) { + throw parseToException("a direction (north, east, south, west, up, down)", valueString, + methodName); + } + } + else if (param == RabbitType.class) { + try { + for (RabbitType type : RabbitType.values()) { + if (type.name().replace("_", "") + .equalsIgnoreCase(valueString.replace("_", "").replace(" ", ""))) { + value = type; + + break; + } + } + if (value == null) { + throw new Exception(); + } + } + catch (Exception ex) { + throw parseToException("rabbit type (white, brown, patches...)", valueString, methodName); + } + } + else if (param == BlockPosition.class) { + try { + String[] split = valueString.split(","); + + assert split.length == 3; + + value = new BlockPosition(Integer.parseInt(split[0]), Integer.parseInt(split[1]), + Integer.parseInt(split[2])); + } + catch (Exception ex) { + throw parseToException("three numbers Number,Number,Number", valueString, methodName); + } + } + } + + if (value == null && boolean.class == param) { + if (valueString == null) { + value = true; + i--; + } + else if (valueString.equalsIgnoreCase("true")) { + value = true; + } + else if (valueString.equalsIgnoreCase("false")) { + value = false; + } + else { + if (getMethod(methods, valueString, 0) == null) { + throw parseToException("true/false", valueString, methodName); + } + else { + value = true; + i--; + } + } + } + + if (value != null) { + break; + } + } + catch (DisguiseParseException ex) { + storedEx = ex; + methodToUse = null; + } + catch (Exception ex) { + ex.printStackTrace(); + methodToUse = null; + } + } + + if (methodToUse == null) { + if (storedEx != null) { + throw storedEx; + } + + throw new DisguiseParseException(ChatColor.RED + "Cannot find the option " + methodName); + } + if (value == null) { + throw new DisguiseParseException(ChatColor.RED + "No value was given for the option " + methodName); + } + + if (!usedOptions.contains(methodName.toLowerCase())) { + usedOptions.add(methodName.toLowerCase()); + } + + doCheck(optionPermissions, usedOptions); + + if (FlagWatcher.class.isAssignableFrom(methodToUse.getDeclaringClass())) { + methodToUse.invoke(disguise.getWatcher(), value); + } + else { + methodToUse.invoke(disguise, value); + } + } + // Alright. We've constructed our disguise. + return disguise; + } + + private static DisguiseParseException parseToException(String expectedValue, String receivedInstead, String methodName) { + return new DisguiseParseException( + ChatColor.RED + "Expected " + ChatColor.GREEN + expectedValue + ChatColor.RED + ", received " + ChatColor.GREEN + + receivedInstead + ChatColor.RED + " instead for " + ChatColor.GREEN + methodName); + } + + private static ItemStack parseToItemstack(String string) throws Exception { + String[] split = string.split(":", -1); + + int itemId = -1; + + if (isNumeric(split[0])) { + itemId = Integer.parseInt(split[0]); + } + else { + try { + itemId = Material.valueOf(split[0].toUpperCase()).getId(); + } + catch (Exception ex) { + } + } + + if (itemId != -1) { + short itemDura = 0; + + if (split.length > 1) { + if (isNumeric(split[1])) { + itemDura = Short.parseShort(split[1]); + } + else { + throw parseToException("item ID:Durability combo", string, "%s"); + } + } + + return new ItemStack(itemId, 1, itemDura); + } + else { + if (split.length == 1) { + throw parseToException("item ID", string, "%s"); + } + else { + throw parseToException("item ID:Durability combo", string, "%s"); + } + } + } + + private static boolean passesCheck(HashMap, Boolean> theirPermissions, ArrayList usedOptions) { + boolean hasPermission = false; + + for (ArrayList list : theirPermissions.keySet()) { + boolean myPerms = true; + + for (String option : usedOptions) { + if (!(theirPermissions.get(list) && list.contains("*")) + && (list.contains(option) != theirPermissions.get(list))) { + myPerms = false; + break; + } + } + + if (myPerms) { + hasPermission = true; + } + } + return hasPermission; + } +} diff --git a/src/me/libraryaddict/disguise/utilities/LibsProfileLookup.java b/src/me/libraryaddict/disguise/utilities/LibsProfileLookup.java index aff0abb4..10dbc70d 100644 --- a/src/me/libraryaddict/disguise/utilities/LibsProfileLookup.java +++ b/src/me/libraryaddict/disguise/utilities/LibsProfileLookup.java @@ -1,9 +1,9 @@ -package me.libraryaddict.disguise.utilities; - -import com.comphenix.protocol.wrappers.WrappedGameProfile; - -public interface LibsProfileLookup { - - void onLookup(WrappedGameProfile gameProfile); - -} +package me.libraryaddict.disguise.utilities; + +import com.comphenix.protocol.wrappers.WrappedGameProfile; + +public interface LibsProfileLookup { + + void onLookup(WrappedGameProfile gameProfile); + +} diff --git a/src/me/libraryaddict/disguise/utilities/ReflectionFlagWatchers.java b/src/me/libraryaddict/disguise/utilities/ReflectionFlagWatchers.java index ebbd1bfe..b157a936 100644 --- a/src/me/libraryaddict/disguise/utilities/ReflectionFlagWatchers.java +++ b/src/me/libraryaddict/disguise/utilities/ReflectionFlagWatchers.java @@ -26,6 +26,7 @@ import me.libraryaddict.disguise.disguisetypes.AnimalColor; import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.FlagWatcher; +import me.libraryaddict.disguise.utilities.DisguiseParser.DisguisePerm; public class ReflectionFlagWatchers { public static class ParamInfo { @@ -107,6 +108,10 @@ public class ReflectionFlagWatchers { return null; } + public static ParamInfo getParamInfo(DisguisePerm disguiseType, String methodName) { + return getParamInfo(disguiseType.getType(), methodName); + } + public static ParamInfo getParamInfo(DisguiseType disguiseType, String methodName) { for (Method method : getDisguiseWatcherMethods(disguiseType.getWatcherClass())) { if (!method.getName().toLowerCase().equals(methodName.toLowerCase())) diff --git a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java index 8e8e6806..f149a63a 100644 --- a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -5,7 +5,10 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Map; import java.util.UUID; +import java.util.regex.Pattern; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -33,8 +36,10 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry; import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer; import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.protocol.wrappers.WrappedSignedProperty; import com.comphenix.protocol.wrappers.WrappedWatchableObject; import com.google.common.base.Optional; +import com.google.gson.Gson; import me.libraryaddict.disguise.disguisetypes.DisguiseType; @@ -91,6 +96,42 @@ public class ReflectionManager { entityCountField.setAccessible(true); } + public static WrappedGameProfile parseGameProfile(String toParse) { + Map response = new Gson().fromJson(toParse, Map.class); + + String id = (String) response.get("id"); + + if (!id.contains("-")) { + id = Pattern.compile("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)").matcher(id) + .replaceFirst("$1-$2-$3-$4-$5"); + } + + WrappedGameProfile gameProfile = new WrappedGameProfile(UUID.fromString(id), (String) response.get("name")); + + if (response.containsKey("properties")) { + ArrayList> properties = (ArrayList) response.get("properties"); + + for (Map s : properties) { + String gName = null; + String gValue = null; + String gSigned = null; + + if (s.containsKey("name")) + gName = s.get("name"); + + if (s.containsKey("value")) + gValue = s.get("value"); + + if (s.containsKey("signature")) + gSigned = s.get("signature"); + + gameProfile.getProperties().put(gName, new WrappedSignedProperty(gName, gValue, gSigned)); + } + } + + return gameProfile; + } + public static Object createEntityInstance(String entityName) { try { Class entityClass = getNmsClass("Entity" + entityName);