mirror of
https://github.com/EssentialsX/Essentials.git
synced 2025-01-03 15:08:18 +01:00
Make HelpInput use the known command map (#3675)
Co-authored-by: MD <1917406+md678685@users.noreply.github.com> This PR makes HelpInput use knownCommands in the command map, rather than relying on plugin descriptions. This means that commands that have been registered programmatically (or impromptu) will be recognized and displayed in the help menu. The ugly reflection is due to Spigot not exposing the command map getter. This has been tested on Spigot 1.8, 1.16.3 and Paper 1.16.3 with plugins that register commands directly to the command map.
This commit is contained in:
parent
583bf88207
commit
a4f580e319
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* TODO: Use the real commandmap to do this automatically.
|
||||
*/
|
||||
protected final List<String> getCommands(final Server server) {
|
||||
final List<String> commands = Lists.newArrayList();
|
||||
for (final Plugin p : server.getPluginManager().getPlugins()) {
|
||||
final PluginDescriptionFile desc = p.getDescription();
|
||||
final Map<String, Map<String, Object>> cmds = desc.getCommands();
|
||||
if (cmds != null) {
|
||||
commands.addAll(cmds.keySet());
|
||||
protected final List<String> getCommands(Server server) {
|
||||
final Map<String, Command> commandMap = Maps.newHashMap(this.ess.getKnownCommandsProvider().getKnownCommands());
|
||||
final List<String> commands = Lists.newArrayListWithCapacity(commandMap.size());
|
||||
for (final Command command : commandMap.values()) {
|
||||
if (!(command instanceof PluginIdentifiableCommand)) {
|
||||
continue;
|
||||
}
|
||||
commands.add(command.getName());
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
@ -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<String> lines = new ArrayList<>();
|
||||
private final transient List<String> chapters = new ArrayList<>();
|
||||
private final transient Map<String, Integer> 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<String> 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<Plugin, Command> 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<String> 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<String, Map<String, Object>> 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<String, Object> 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<Object>) 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<Object>) 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
package net.ess3.provider;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface KnownCommandsProvider extends Provider {
|
||||
Map<String, Command> getKnownCommands();
|
||||
}
|
@ -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<String, Command> knownCommands;
|
||||
|
||||
public ReflKnownCommandsProvider() {
|
||||
Map<String, Command> knownCommands = new HashMap<>();
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends Server> craftServerClass = (Class<? extends Server>) 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<String, Command>) knownCommandsField.get(simpleCommandMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final Exception exception) {
|
||||
exception.printStackTrace();
|
||||
} finally {
|
||||
this.knownCommands = knownCommands;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Command> getKnownCommands() {
|
||||
return this.knownCommands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "NMS Reflection Known Commands Provider";
|
||||
}
|
||||
}
|
@ -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<String, Command> getKnownCommands() {
|
||||
return Bukkit.getCommandMap().getKnownCommands();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Paper Known Commands Provider";
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user