diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java index 933a4b6b7..709c1b263 100644 --- a/Essentials/src/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/com/earth2me/essentials/Essentials.java @@ -47,7 +47,9 @@ import net.ess3.api.ISettings; import net.ess3.nms.refl.providers.ReflServerStateProvider; import net.ess3.nms.refl.providers.ReflSpawnEggProvider; import net.ess3.nms.refl.providers.ReflSpawnerBlockProvider; +import net.ess3.nms.refl.providers.ReflKnownCommandsProvider; import net.ess3.provider.ContainerProvider; +import net.ess3.provider.KnownCommandsProvider; import net.ess3.provider.PotionMetaProvider; import net.ess3.provider.ProviderListener; import net.ess3.provider.ServerStateProvider; @@ -61,6 +63,7 @@ import net.ess3.provider.providers.FlatSpawnEggProvider; import net.ess3.provider.providers.LegacyPotionMetaProvider; import net.ess3.provider.providers.LegacySpawnEggProvider; import net.ess3.provider.providers.PaperContainerProvider; +import net.ess3.provider.providers.PaperKnownCommandsProvider; import net.ess3.provider.providers.PaperRecipeBookListener; import net.ess3.provider.providers.PaperServerStateProvider; import org.bukkit.Bukkit; @@ -134,6 +137,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { private transient PotionMetaProvider potionMetaProvider; private transient ServerStateProvider serverStateProvider; private transient ContainerProvider containerProvider; + private transient KnownCommandsProvider knownCommandsProvider; private transient ProviderListener recipeBookEventProvider; private transient Kits kits; private transient RandomTeleport randomTeleport; @@ -324,6 +328,13 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { } } + //Known Commands Provider + if (PaperLib.isPaper() && VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01)) { + knownCommandsProvider = new PaperKnownCommandsProvider(); + } else { + knownCommandsProvider = new ReflKnownCommandsProvider(); + } + execTimer.mark("Init(Providers)"); reload(); @@ -1013,6 +1024,11 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials { return containerProvider; } + @Override + public KnownCommandsProvider getKnownCommandsProvider() { + return knownCommandsProvider; + } + private AbstractItemDb getItemDbFromConfig() { final String setting = settings.getItemDbType(); diff --git a/Essentials/src/com/earth2me/essentials/IEssentials.java b/Essentials/src/com/earth2me/essentials/IEssentials.java index 98294dfee..dda4eba61 100644 --- a/Essentials/src/com/earth2me/essentials/IEssentials.java +++ b/Essentials/src/com/earth2me/essentials/IEssentials.java @@ -5,6 +5,7 @@ import com.earth2me.essentials.api.IJails; import com.earth2me.essentials.api.IWarps; import com.earth2me.essentials.perm.PermissionsHandler; import net.ess3.provider.ContainerProvider; +import net.ess3.provider.KnownCommandsProvider; import net.ess3.provider.ServerStateProvider; import net.ess3.provider.SpawnerBlockProvider; import net.ess3.provider.SpawnerItemProvider; @@ -115,4 +116,6 @@ public interface IEssentials extends Plugin { ServerStateProvider getServerStateProvider(); ContainerProvider getContainerProvider(); + + KnownCommandsProvider getKnownCommandsProvider(); } diff --git a/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java b/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java index 5af932a6d..af261d804 100644 --- a/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java +++ b/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java @@ -7,13 +7,14 @@ import com.earth2me.essentials.User; import com.earth2me.essentials.utils.FormatUtil; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import net.ess3.api.IEssentials; import org.bukkit.Server; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginIdentifiableCommand; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.util.StringUtil; import java.util.ArrayList; @@ -309,17 +310,15 @@ public abstract class EssentialsCommand implements IEssentialsCommand { /** * Lists all commands. - *

- * TODO: Use the real commandmap to do this automatically. */ - protected final List getCommands(final Server server) { - final List commands = Lists.newArrayList(); - for (final Plugin p : server.getPluginManager().getPlugins()) { - final PluginDescriptionFile desc = p.getDescription(); - final Map> cmds = desc.getCommands(); - if (cmds != null) { - commands.addAll(cmds.keySet()); + protected final List getCommands(Server server) { + final Map commandMap = Maps.newHashMap(this.ess.getKnownCommandsProvider().getKnownCommands()); + final List commands = Lists.newArrayListWithCapacity(commandMap.size()); + for (final Command command : commandMap.values()) { + if (!(command instanceof PluginIdentifiableCommand)) { + continue; } + commands.add(command.getName()); } return commands; } diff --git a/Essentials/src/com/earth2me/essentials/textreader/HelpInput.java b/Essentials/src/com/earth2me/essentials/textreader/HelpInput.java index 859a5f30a..dd3442c80 100644 --- a/Essentials/src/com/earth2me/essentials/textreader/HelpInput.java +++ b/Essentials/src/com/earth2me/essentials/textreader/HelpInput.java @@ -1,11 +1,14 @@ package com.earth2me.essentials.textreader; import com.earth2me.essentials.User; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import net.ess3.api.IEssentials; +import org.bukkit.command.Command; +import org.bukkit.command.PluginIdentifiableCommand; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -17,15 +20,12 @@ import java.util.logging.Logger; import static com.earth2me.essentials.I18n.tl; public class HelpInput implements IText { - private static final String DESCRIPTION = "description"; - private static final String PERMISSION = "permission"; - private static final String PERMISSIONS = "permissions"; private static final Logger logger = Logger.getLogger("Essentials"); private final transient List lines = new ArrayList<>(); private final transient List chapters = new ArrayList<>(); private final transient Map bookmarks = new HashMap<>(); - public HelpInput(final User user, final String match, final IEssentials ess) throws IOException { + public HelpInput(final User user, final String match, final IEssentials ess) { boolean reported = false; final List newLines = new ArrayList<>(); String pluginName = ""; @@ -34,7 +34,16 @@ public class HelpInput implements IText { lines.add(tl("helpMatching", match)); } - for (final Plugin p : ess.getServer().getPluginManager().getPlugins()) { + final Multimap pluginCommands = HashMultimap.create(); + for (final Command command : ess.getKnownCommandsProvider().getKnownCommands().values()) { + if (!(command instanceof PluginIdentifiableCommand)) { + continue; + } + final PluginIdentifiableCommand pluginIdentifiableCommand = (PluginIdentifiableCommand) command; + pluginCommands.put(pluginIdentifiableCommand.getPlugin(), command); + } + + for (Plugin p : ess.getServer().getPluginManager().getPlugins()) { try { final List pluginLines = new ArrayList<>(); final PluginDescriptionFile desc = p.getDescription(); @@ -48,46 +57,51 @@ public class HelpInput implements IText { } final boolean isOnWhitelist = user.isAuthorized("essentials.help." + pluginNameLow); - for (final Map.Entry> k : cmds.entrySet()) { + for (final Command command : pluginCommands.get(p)) { try { - if (!match.equalsIgnoreCase("") && !pluginNameLow.contains(match) && !k.getKey().toLowerCase(Locale.ENGLISH).contains(match) && !(k.getValue().get(DESCRIPTION) instanceof String && ((String) k.getValue().get(DESCRIPTION)).toLowerCase(Locale.ENGLISH).contains(match))) { + final String commandName = command.getName(); + final String commandDescription = command.getDescription(); + + if (!match.equalsIgnoreCase("") + && (!pluginNameLow.contains(match)) + && (!commandName.toLowerCase(Locale.ENGLISH).contains(match)) + && (!commandDescription.toLowerCase(Locale.ENGLISH).contains(match))) { continue; } if (pluginNameLow.contains("essentials")) { - final String node = "essentials." + k.getKey(); - if (!ess.getSettings().isCommandDisabled(k.getKey()) && user.isAuthorized(node)) { - pluginLines.add(tl("helpLine", k.getKey(), k.getValue().get(DESCRIPTION))); + final String node = "essentials." + commandName; + if (!ess.getSettings().isCommandDisabled(commandName) && user.isAuthorized(node)) { + pluginLines.add(tl("helpLine", commandName, commandDescription)); } } else { if (ess.getSettings().showNonEssCommandsInHelp()) { - final Map value = k.getValue(); - Object permissions = null; - if (value.containsKey(PERMISSION)) { - permissions = value.get(PERMISSION); - } else if (value.containsKey(PERMISSIONS)) { - permissions = value.get(PERMISSIONS); + final String permissionRaw = command.getPermission(); + final String[] permissions; + if (permissionRaw == null) { + permissions = new String[0]; + } else { + permissions = permissionRaw.split(";"); } - if (isOnWhitelist || user.isAuthorized("essentials.help." + pluginNameLow + "." + k.getKey())) { - pluginLines.add(tl("helpLine", k.getKey(), value.get(DESCRIPTION))); - } else if (permissions instanceof List && !((List) permissions).isEmpty()) { + + if (isOnWhitelist || user.isAuthorized("essentials.help." + pluginNameLow + "." + commandName)) { + pluginLines.add(tl("helpLine", commandName, commandDescription)); + } else if (permissions.length != 0) { boolean enabled = false; - for (final Object o : (List) permissions) { - if (o instanceof String && user.isAuthorized(o.toString())) { + + for (final String permission : permissions) { + if (user.isAuthorized(permission)) { enabled = true; break; } } + if (enabled) { - pluginLines.add(tl("helpLine", k.getKey(), value.get(DESCRIPTION))); - } - } else if (permissions instanceof String && !"".equals(permissions)) { - if (user.isAuthorized(permissions.toString())) { - pluginLines.add(tl("helpLine", k.getKey(), value.get(DESCRIPTION))); + pluginLines.add(tl("helpLine", commandName, commandDescription)); } } else { if (!ess.getSettings().hidePermissionlessHelp()) { - pluginLines.add(tl("helpLine", k.getKey(), value.get(DESCRIPTION))); + pluginLines.add(tl("helpLine", commandName, commandDescription)); } } } diff --git a/providers/BaseProviders/src/net/ess3/provider/KnownCommandsProvider.java b/providers/BaseProviders/src/net/ess3/provider/KnownCommandsProvider.java new file mode 100644 index 000000000..952db7136 --- /dev/null +++ b/providers/BaseProviders/src/net/ess3/provider/KnownCommandsProvider.java @@ -0,0 +1,9 @@ +package net.ess3.provider; + +import org.bukkit.command.Command; + +import java.util.Map; + +public interface KnownCommandsProvider extends Provider { + Map getKnownCommands(); +} diff --git a/providers/NMSReflectionProvider/src/net/ess3/nms/refl/providers/ReflKnownCommandsProvider.java b/providers/NMSReflectionProvider/src/net/ess3/nms/refl/providers/ReflKnownCommandsProvider.java new file mode 100644 index 000000000..19c558d56 --- /dev/null +++ b/providers/NMSReflectionProvider/src/net/ess3/nms/refl/providers/ReflKnownCommandsProvider.java @@ -0,0 +1,48 @@ +package net.ess3.nms.refl.providers; + +import net.ess3.nms.refl.ReflUtil; +import net.ess3.provider.KnownCommandsProvider; +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.command.Command; +import org.bukkit.command.SimpleCommandMap; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +public class ReflKnownCommandsProvider implements KnownCommandsProvider { + private final Map knownCommands; + + public ReflKnownCommandsProvider() { + Map knownCommands = new HashMap<>(); + try { + @SuppressWarnings("unchecked") + final Class craftServerClass = (Class) ReflUtil.getOBCClass("CraftServer"); + if (craftServerClass != null) { + final Field commandMapField = ReflUtil.getFieldCached(craftServerClass, "commandMap"); + if (commandMapField != null) { + final SimpleCommandMap simpleCommandMap = (SimpleCommandMap) commandMapField.get(Bukkit.getServer()); + final Field knownCommandsField = ReflUtil.getFieldCached(SimpleCommandMap.class, "knownCommands"); + if (knownCommandsField != null) { + knownCommands = (Map) knownCommandsField.get(simpleCommandMap); + } + } + } + } catch (final Exception exception) { + exception.printStackTrace(); + } finally { + this.knownCommands = knownCommands; + } + } + + @Override + public Map getKnownCommands() { + return this.knownCommands; + } + + @Override + public String getDescription() { + return "NMS Reflection Known Commands Provider"; + } +} diff --git a/providers/PaperProvider/src/net/ess3/provider/providers/PaperKnownCommandsProvider.java b/providers/PaperProvider/src/net/ess3/provider/providers/PaperKnownCommandsProvider.java new file mode 100644 index 000000000..b1666962b --- /dev/null +++ b/providers/PaperProvider/src/net/ess3/provider/providers/PaperKnownCommandsProvider.java @@ -0,0 +1,19 @@ +package net.ess3.provider.providers; + +import net.ess3.provider.KnownCommandsProvider; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; + +import java.util.Map; + +public class PaperKnownCommandsProvider implements KnownCommandsProvider { + @Override + public Map getKnownCommands() { + return Bukkit.getCommandMap().getKnownCommands(); + } + + @Override + public String getDescription() { + return "Paper Known Commands Provider"; + } +}