ShopChest/src/main/java/de/epiceric/shopchest/command/ShopCommand.java

349 lines
13 KiB
Java

package de.epiceric.shopchest.command;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.config.Placeholder;
import de.epiceric.shopchest.language.LanguageUtils;
import de.epiceric.shopchest.language.Message;
import de.epiceric.shopchest.language.Replacement;
import de.epiceric.shopchest.utils.Permissions;
import de.epiceric.shopchest.utils.ClickType.SelectClickType;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class ShopCommand {
private static boolean commandCreated = false;
private final ShopChest plugin;
private final String name;
private final String fallbackPrefix;
private final PluginCommand pluginCommand;
private final ShopCommandExecutor executor;
private final List<ShopSubCommand> subCommands = new ArrayList<>();
public ShopCommand(final ShopChest plugin) {
if (commandCreated) {
IllegalStateException e = new IllegalStateException("Command has already been registered");
plugin.debug(e);
throw e;
}
this.plugin = plugin;
this.name = Config.mainCommandName.toLowerCase(Locale.ENGLISH).trim();
this.fallbackPrefix = plugin.getName().toLowerCase(Locale.ENGLISH).trim();
this.pluginCommand = createPluginCommand();
this.executor = new ShopCommandExecutor(plugin);
ShopTabCompleter tabCompleter = new ShopTabCompleter(plugin);
final Replacement cmdReplacement = new Replacement(Placeholder.COMMAND, name);
addSubCommand(new ShopSubCommand("create", true, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
boolean receiveCreateMessage = sender.hasPermission(Permissions.CREATE);
if (!receiveCreateMessage) {
for (PermissionAttachmentInfo permInfo : sender.getEffectivePermissions()) {
String perm = permInfo.getPermission();
if (perm.startsWith(Permissions.CREATE) && sender.hasPermission(perm)) {
receiveCreateMessage = true;
break;
}
}
}
if (sender.hasPermission(Permissions.CREATE_ADMIN)) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_CREATE_ADMIN, cmdReplacement);
} else if (receiveCreateMessage) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_CREATE, cmdReplacement);
}
return "";
}
});
addSubCommand(new ShopSubCommand("remove", true, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_REMOVE, cmdReplacement);
}
});
addSubCommand(new ShopSubCommand("info", true, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_INFO, cmdReplacement);
}
});
addSubCommand(new ShopSubCommand("limits", true, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_LIMITS, cmdReplacement);
}
});
addSubCommand(new ShopSubCommand("open", true, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_OPEN, cmdReplacement);
}
});
addSubCommand(new ShopSubCommand("removeall", false, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
if (sender.hasPermission(Permissions.REMOVE_OTHER)) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_REMOVEALL, cmdReplacement);
} else {
return "";
}
}
});
addSubCommand(new ShopSubCommand("reload", false, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
if (sender.hasPermission(Permissions.RELOAD)) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_RELOAD, cmdReplacement);
} else {
return "";
}
}
});
addSubCommand(new ShopSubCommand("update", false, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
if (sender.hasPermission(Permissions.UPDATE)) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_UPDATE, cmdReplacement);
} else {
return "";
}
}
});
addSubCommand(new ShopSubCommand("config", false, executor, tabCompleter) {
@Override
public String getHelpMessage(CommandSender sender) {
if (sender.hasPermission(Permissions.CONFIG)) {
return LanguageUtils.getMessage(Message.COMMAND_DESC_CONFIG, cmdReplacement);
} else {
return "";
}
}
});
register();
commandCreated = true;
}
public PluginCommand getCommand() {
return pluginCommand;
}
/**
* Call the second part of the create method after the player
* has selected an item from the creative inventory.
*/
public void createShopAfterSelected(Player player, SelectClickType clickType) {
executor.create2(player, clickType);
}
private PluginCommand createPluginCommand() {
plugin.debug("Creating plugin command");
try {
Constructor<PluginCommand> c = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
c.setAccessible(true);
PluginCommand cmd = c.newInstance(name, plugin);
cmd.setDescription("Manage players' shops or this plugin.");
cmd.setUsage("/" + name);
cmd.setExecutor(new ShopBaseCommandExecutor());
cmd.setTabCompleter(new ShopBaseTabCompleter());
return cmd;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
plugin.getLogger().severe("Failed to create command");
plugin.debug("Failed to create plugin command");
plugin.debug(e);
}
return null;
}
public void addSubCommand(ShopSubCommand subCommand) {
plugin.debug("Adding sub command \"" + subCommand.getName() + "\"");
this.subCommands.add(subCommand);
}
public List<ShopSubCommand> getSubCommands() {
return new ArrayList<>(subCommands);
}
private void register() {
if (pluginCommand == null) return;
plugin.debug("Registering command " + name);
try {
Field fCommandMap = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
fCommandMap.setAccessible(true);
Object commandMapObject = fCommandMap.get(Bukkit.getPluginManager());
if (commandMapObject instanceof CommandMap) {
CommandMap commandMap = (CommandMap) commandMapObject;
commandMap.register(fallbackPrefix, pluginCommand);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
plugin.getLogger().severe("Failed to register command");
plugin.debug("Failed to register plugin command");
plugin.debug(e);
}
}
public void unregister() {
if (pluginCommand == null) return;
plugin.debug("Unregistering command " + name);
try {
Field fCommandMap = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
fCommandMap.setAccessible(true);
Object commandMapObject = fCommandMap.get(Bukkit.getPluginManager());
if (commandMapObject instanceof CommandMap) {
CommandMap commandMap = (CommandMap) commandMapObject;
pluginCommand.unregister(commandMap);
Field fKnownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands");
fKnownCommands.setAccessible(true);
Object knownCommandsObject = fKnownCommands.get(commandMap);
if (knownCommandsObject instanceof Map) {
Map<?, ?> knownCommands = (Map<?, ?>) knownCommandsObject;
knownCommands.remove(fallbackPrefix + ":" + name);
if (pluginCommand.equals(knownCommands.get(name))) {
knownCommands.remove(name);
}
}
}
} catch (NoSuchFieldException | IllegalAccessException e) {
plugin.getLogger().severe("Failed to unregister command");
plugin.debug("Failed to unregister plugin command");
plugin.debug(e);
}
}
/**
* Sends the basic help message
*
* @param sender {@link CommandSender} who will receive the message
*/
private void sendBasicHelpMessage(CommandSender sender) {
plugin.debug("Sending basic help message to " + sender.getName());
sender.sendMessage(" ");
String header = LanguageUtils.getMessage(Message.COMMAND_DESC_HEADER,
new Replacement(Placeholder.COMMAND, Config.mainCommandName));
if (!header.trim().isEmpty()) sender.sendMessage(header);
for (ShopSubCommand subCommand : subCommands) {
String msg = subCommand.getHelpMessage(sender);
if (msg == null || msg.isEmpty()) {
continue;
}
sender.sendMessage(msg);
}
String footer = LanguageUtils.getMessage(Message.COMMAND_DESC_FOOTER,
new Replacement(Placeholder.COMMAND,Config.mainCommandName));
if (!footer.trim().isEmpty()) sender.sendMessage(footer);
sender.sendMessage(" ");
}
private class ShopBaseCommandExecutor implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length > 0) {
for (ShopSubCommand subCommand : subCommands) {
if (subCommand.getName().equalsIgnoreCase(args[0])) {
if (!(sender instanceof Player) && subCommand.isPlayerCommand()) {
sender.sendMessage(ChatColor.RED + "Only players can use this command.");
return true;
}
if (!subCommand.execute(sender, command, label, args)) {
sendBasicHelpMessage(sender);
}
return true;
}
}
sendBasicHelpMessage(sender);
} else {
sendBasicHelpMessage(sender);
}
return true;
}
}
private class ShopBaseTabCompleter implements TabCompleter {
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
List<String> subCommandNames = new ArrayList<>();
List<String> tabCompletions = new ArrayList<>();
for (ShopSubCommand subCommand : subCommands) {
subCommandNames.add(subCommand.getName());
}
if (args.length == 1) {
if (!args[0].isEmpty()) {
for (String s : subCommandNames) {
if (s.startsWith(args[0])) {
tabCompletions.add(s);
}
}
return tabCompletions;
} else {
return subCommandNames;
}
} else if (args.length > 1) {
for (ShopSubCommand subCmd : subCommands) {
if (subCmd.getName().equalsIgnoreCase(args[0])) {
return subCmd.getTabCompletions(sender, command, label, args);
}
}
}
return new ArrayList<>();
}
}
}