diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCommand.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCommand.java index 07b3f96d3..cc52673fa 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCommand.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCommand.java @@ -2,9 +2,15 @@ package com.github.intellectualsites.plotsquared.plot.commands; import com.github.intellectualsites.plotsquared.commands.Command; import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; +import com.github.intellectualsites.plotsquared.plot.PlotSquared; +import com.github.intellectualsites.plotsquared.plot.config.CaptionUtility; import com.github.intellectualsites.plotsquared.plot.config.Captions; +import com.github.intellectualsites.plotsquared.plot.config.Settings; +import com.github.intellectualsites.plotsquared.plot.flags.FlagParseException; import com.github.intellectualsites.plotsquared.plot.flags.GlobalFlagContainer; import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; +import com.github.intellectualsites.plotsquared.plot.flags.types.IntegerFlag; +import com.github.intellectualsites.plotsquared.plot.flags.types.ListFlag; import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotMessage; @@ -12,23 +18,82 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3; import com.github.intellectualsites.plotsquared.plot.util.MainUtil; +import com.github.intellectualsites.plotsquared.plot.util.MathMan; import com.github.intellectualsites.plotsquared.plot.util.Permissions; import com.github.intellectualsites.plotsquared.plot.util.StringComparison; +import com.github.intellectualsites.plotsquared.plot.util.StringMan; +import com.github.intellectualsites.plotsquared.plot.util.helpmenu.HelpMenu; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; @CommandDeclaration(command = "flag", aliases = {"f", - "flag"}, usage = "/plot flag ", - description = "Manage plot flags", - category = CommandCategory.SETTINGS, - requiredType = RequiredType.NONE, - permission = "plots.flag") -public class FlagCommand extends SubCommand { + "flag"}, usage = "/plot flag ", description = "Manage plot flags", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, permission = "plots.flag") +@SuppressWarnings("unused") public final class FlagCommand extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, getUsage()); - return false; + private static boolean checkPermValue(@Nonnull final PlotPlayer player, + @NotNull final PlotFlag flag, @NotNull String key, @NotNull String value) { + key = key.toLowerCase(); + value = value.toLowerCase(); + String perm = CaptionUtility + .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), key.toLowerCase(), + value.toLowerCase()); + if (flag instanceof IntegerFlag && MathMan.isInteger(value)) { + try { + int numeric = Integer.parseInt(value); + perm = perm.substring(0, perm.length() - value.length() - 1); + if (numeric > 0) { + int checkRange = PlotSquared.get().getPlatform().equalsIgnoreCase("bukkit") ? + numeric : + Settings.Limit.MAX_PLOTS; + final boolean result = player.hasPermissionRange(perm, checkRange) >= numeric; + if (!result) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, CaptionUtility + .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), + key.toLowerCase(), value.toLowerCase())); + } + return result; + } + + } catch (NumberFormatException ignore) { + } + } else if (flag instanceof ListFlag) { + final ListFlag listFlag = (ListFlag) flag; + try { + PlotFlag, ?> parsedFlag = listFlag.parse(value); + for (final Object entry : parsedFlag.getValue()) { + final String permission = CaptionUtility + .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), + key.toLowerCase(), entry.toString().toLowerCase()); + final boolean result = Permissions.hasPermission(player, permission); + if (!result) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, CaptionUtility + .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), + key.toLowerCase(), value.toLowerCase())); + return false; + } + } + } catch (final Exception e) { + return false; + } + return true; + } + final boolean result = Permissions.hasPermission(player, perm); + if (!result) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, CaptionUtility + .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), key.toLowerCase(), + value.toLowerCase())); + } + return result; } /** @@ -36,7 +101,7 @@ public class FlagCommand extends SubCommand { * * @return true if the player is allowed to modify the flags at their current location */ - private boolean checkRequirements(final PlotPlayer player) { + private static boolean checkRequirements(@NotNull final PlotPlayer player) { final Location location = player.getLocation(); final Plot plot = location.getPlotAbs(); if (plot == null) { @@ -47,8 +112,10 @@ public class FlagCommand extends SubCommand { sendMessage(player, Captions.PLOT_NOT_CLAIMED); return false; } - if (!plot.isOwner(player.getUUID()) && !Permissions.hasPermission(player, Captions.PERMISSION_SET_FLAG_OTHER)) { - MainUtil.sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_SET_FLAG_OTHER); + if (!plot.isOwner(player.getUUID()) && !Permissions + .hasPermission(player, Captions.PERMISSION_SET_FLAG_OTHER)) { + MainUtil + .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_SET_FLAG_OTHER); return false; } return true; @@ -59,17 +126,19 @@ public class FlagCommand extends SubCommand { * be found, a flag suggestion may be sent to the player. * * @param player Player executing the command - * @param arg String to extract flag from + * @param arg String to extract flag from * @return The flag, if found, else null */ - @Nullable private PlotFlag getFlag(final PlotPlayer player, final String arg) { + @Nullable private static PlotFlag getFlag(@NotNull final PlotPlayer player, + @NotNull final String arg) { if (arg != null && arg.length() > 0) { - final PlotFlag flag = GlobalFlagContainer.getInstance().getFlagFromString(arg); + final PlotFlag flag = GlobalFlagContainer.getInstance().getFlagFromString(arg); if (flag == null) { boolean suggested = false; try { final StringComparison> stringComparison = - new StringComparison<>(arg, GlobalFlagContainer.getInstance().getFlagMap().values()); + new StringComparison<>(arg, + GlobalFlagContainer.getInstance().getFlagMap().values()); final String best = stringComparison.getBestMatch(); if (best != null) { MainUtil.sendMessage(player, Captions.NOT_VALID_FLAG_SUGGESTED, best); @@ -86,61 +155,204 @@ public class FlagCommand extends SubCommand { return null; } - @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { + @Override public boolean onCommand(final PlotPlayer player, final String[] args) { + new HelpMenu(player).setCategory(CommandCategory.SETTINGS).setCommands(this.getCommands()) + .generateMaxPages() + .generatePage(0, getParent().toString()).render(); + return true; + } + + @Override public Collection tab(final PlotPlayer player, final String[] args, + final boolean space) { return tabOf(player, args, space, getUsage()); } - @CommandDeclaration(command = "set", aliases = {"s", "set"}, - usage = "/plot flag set ", - description = "Set a plot flag", - category = CommandCategory.SETTINGS, - requiredType = RequiredType.NONE, - permission = "plots.flag.set") - public void set(Command command, PlotPlayer player, String[] args, - RunnableVal3 confirm, - RunnableVal2 whenDone) { + @CommandDeclaration(command = "set", aliases = {"s", + "set"}, usage = "/plot flag set ", description = "Set a plot flag", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, permission = "plots.set.flag") + public void set(final Command command, final PlotPlayer player, final String[] args, + final RunnableVal3 confirm, + final RunnableVal2 whenDone) { if (!checkRequirements(player)) { return; } + if (args.length < 2) { + MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, "/plot flag set "); + return; + } + final PlotFlag plotFlag = getFlag(player, args[0]); + if (plotFlag == null) { + return; + } + final String value = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); + if (!checkPermValue(player, plotFlag, args[0], value)) { + return; + } + final PlotFlag parsed; + try { + parsed = plotFlag.parse(value); + } catch (final FlagParseException e) { + Captions.FLAG_PARSE_EXCEPTION + .send(player, e.getFlag().getName(), e.getValue(), e.getErrorMessage()); + return; + } + player.getLocation().getPlotAbs().setFlag(parsed); + MainUtil.sendMessage(player, Captions.FLAG_ADDED); } - @CommandDeclaration(command = "add", aliases = {"a", "add"}, - usage = "/plot flag add ", - description = "Add a plot flag value", - category = CommandCategory.SETTINGS, - requiredType = RequiredType.NONE, - permission = "plots.flag.add") - public void add(Command command, PlotPlayer player, String[] args, - RunnableVal3 confirm, - RunnableVal2 whenDone) { + @CommandDeclaration(command = "add", aliases = {"a", + "add"}, usage = "/plot flag add ", description = "Add a plot flag value", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, permission = "plots.flag.add") + public void add(final Command command, PlotPlayer player, final String[] args, + final RunnableVal3 confirm, + final RunnableVal2 whenDone) { if (!checkRequirements(player)) { return; } + if (args.length < 3) { + MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, "/plot flag add "); + return; + } + final PlotFlag flag = getFlag(player, args[0]); + if (flag == null) { + return; + } + for (String entry : args[1].split(",")) { + if (!checkPermValue(player, flag, args[0], entry)) { + return; + } + } + final String value = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); + final PlotFlag parsed; + try { + parsed = flag.parse(value); + } catch (FlagParseException e) { + Captions.FLAG_PARSE_EXCEPTION + .send(player, e.getFlag().getName(), e.getValue(), e.getErrorMessage()); + return; + } + boolean result = player.getLocation().getPlotAbs() + .setFlag(flag.merge(parsed.getValue())); + if (!result) { + MainUtil.sendMessage(player, Captions.FLAG_NOT_ADDED); + return; + } + MainUtil.sendMessage(player, Captions.FLAG_ADDED); } - @CommandDeclaration(command = "list", aliases = {"l", "list", "flags"}, - usage = "/plot flag list", - description = "List all available plot flags", - category = CommandCategory.SETTINGS, - requiredType = RequiredType.NONE, - permission = "plots.flag.list") - public void list(Command command, PlotPlayer player, String[] args, - RunnableVal3 confirm, - RunnableVal2 whenDone) { + @CommandDeclaration(command = "remove", aliases = {"r", "remove", + "delete"}, usage = "/plot flag remove [values]", description = "Remove a flag", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, permission = "plots.flag.add") + public void remove(final Command command, PlotPlayer player, final String[] args, + final RunnableVal3 confirm, + final RunnableVal2 whenDone) { if (!checkRequirements(player)) { return; } + if (args.length != 1 && args.length != 2) { + MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, "/plot flag remove [values]"); + return; + } + final PlotFlag flag = getFlag(player, args[0]); + if (flag == null) { + return; + } + if (!Permissions.hasPermission(player, + CaptionUtility.format(Captions.PERMISSION_SET_FLAG_KEY.getTranslated(), args[0].toLowerCase()))) { + if (args.length != 2) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, CaptionUtility + .format(Captions.PERMISSION_SET_FLAG_KEY.getTranslated(), args[0].toLowerCase())); + return; + } + } + final Plot plot = player.getLocation().getPlotAbs(); + if (args.length == 2 && flag instanceof ListFlag) { + String value = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); + final ListFlag listFlag = (ListFlag) flag; + final List list = plot.getFlag((Class>) listFlag.getClass()); + final PlotFlag, ?> parsedFlag; + try { + parsedFlag = listFlag.parse(value); + } catch (final FlagParseException e) { + Captions.FLAG_PARSE_EXCEPTION + .send(player, e.getFlag().getName(), e.getValue(), e.getErrorMessage()); + return; + } + if (parsedFlag.getValue().isEmpty()) { + MainUtil.sendMessage(player, Captions.FLAG_NOT_REMOVED); + return; + } + if (list.removeAll(parsedFlag.getValue())) { + if (list.isEmpty()) { + if (plot.removeFlag(flag)) { + MainUtil.sendMessage(player, Captions.FLAG_REMOVED); + return; + } else { + MainUtil.sendMessage(player, Captions.FLAG_NOT_REMOVED); + return; + } + } else { + MainUtil.sendMessage(player, Captions.FLAG_REMOVED); + } + } else { + MainUtil.sendMessage(player, Captions.FLAG_NOT_REMOVED); + return; + } + // TODO reimplement somewhere else: DBFunc.setFlags(plot, plot.getFlags()); + return; + } else { + boolean result = plot.removeFlag(flag); + if (!result) { + MainUtil.sendMessage(player, Captions.FLAG_NOT_REMOVED); + return; + } + } + /* TODO reimplement, maybe handle it with events? + if (flag == Flags.TIME) { + player.setTime(Long.MAX_VALUE); + } else if (flag == Flags.WEATHER) { + player.setWeather(PlotWeather.RESET); + }*/ + MainUtil.sendMessage(player, Captions.FLAG_REMOVED); } - @CommandDeclaration(command = "info", aliases = {"i", "info"}, - usage = "/plot flag info ", - description = "View information about a flag", - category = CommandCategory.SETTINGS, - requiredType = RequiredType.NONE, - permission = "plots.flag.info") - public void info(Command command, PlotPlayer player, String[] args, - RunnableVal3 confirm, - RunnableVal2 whenDone) { + @CommandDeclaration(command = "list", aliases = {"l", "list", + "flags"}, usage = "/plot flag list", description = "List all available plot flags", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, permission = "plots.flag.list") + public void list(final Command command, final PlotPlayer player, final String[] args, + final RunnableVal3 confirm, + final RunnableVal2 whenDone) { + if (!checkRequirements(player)) { + return; + } + + final Map> flags = new HashMap<>(); + for (PlotFlag plotFlag : GlobalFlagContainer.getInstance().getRecognizedPlotFlags()) { + final String category = plotFlag.getFlagCategory().getTranslated(); + final Collection flagList = flags.computeIfAbsent(category, k -> new ArrayList<>()); + flagList.add(plotFlag.getName()); + } + + for (final Map.Entry> entry : flags.entrySet()) { + Collections.sort(entry.getValue()); + PlotMessage plotMessage = new PlotMessage(entry.getKey() + ": ").color(Captions.FLAG_INFO_COLOR_KEY.getTranslated()); + final Iterator flagIterator = entry.getValue().iterator(); + while (flagIterator.hasNext()) { + final String flag = flagIterator.next(); + plotMessage = plotMessage.text(flag).command("/plot flag info " + flag) + .color(Captions.FLAG_INFO_COLOR_VALUE.getTranslated()) + .tooltip(new PlotMessage(Captions.FLAG_LIST_SEE_INFO.getTranslated()) + .color(Captions.FLAG_INFO_COLOR_VALUE.getTranslated())); + if (flagIterator.hasNext()) { + plotMessage = plotMessage.text(", ") + .color(Captions.FLAG_INFO_COLOR_VALUE.getTranslated()); + } + } + plotMessage.send(player); + } + } + + @CommandDeclaration(command = "info", aliases = {"i", + "info"}, usage = "/plot flag info ", description = "View information about a flag", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, permission = "plots.flag.info") + public void info(final Command command, final PlotPlayer player, final String[] args, + final RunnableVal3 confirm, + final RunnableVal2 whenDone) { if (!checkRequirements(player)) { return; } @@ -156,7 +368,8 @@ public class FlagCommand extends SubCommand { .color(Captions.FLAG_INFO_COLOR_VALUE.getTranslated()).send(player); // Flag category new PlotMessage(Captions.FLAG_INFO_CATEGORY.getTranslated()) - .color(Captions.FLAG_INFO_COLOR_KEY.getTranslated()).text(plotFlag.getFlagCategory().getTranslated()) + .color(Captions.FLAG_INFO_COLOR_KEY.getTranslated()) + .text(plotFlag.getFlagCategory().getTranslated()) .color(Captions.FLAG_INFO_COLOR_VALUE.getTranslated()).send(player); // Flag description new PlotMessage(Captions.FLAG_INFO_DESCRIPTION.getTranslated()) @@ -166,8 +379,9 @@ public class FlagCommand extends SubCommand { // Flag example new PlotMessage(Captions.FLAG_INFO_EXAMPLE.getTranslated()) .color(Captions.FLAG_INFO_COLOR_KEY.getTranslated()).text(plotFlag.getExample()) - .color(Captions.FLAG_INFO_COLOR_VALUE.getTranslated()).suggest("/plot flag set " + - plotFlag.getName() + " " + plotFlag.getExample()).send(player); + .color(Captions.FLAG_INFO_COLOR_VALUE.getTranslated()) + .suggest("/plot flag set " + plotFlag.getName() + " " + plotFlag.getExample()) + .send(player); // Default value final String defaultValue = player.getLocation().getPlotArea().getFlagContainer() .getFlagErased(plotFlag.getClass()).toString(); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java index dd060c88e..696c0752e 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/MainCommand.java @@ -86,7 +86,8 @@ public class MainCommand extends Command { new DebugRoadRegen(); new Trust(); new DebugExec(); - new FlagCmd(); + // new FlagCmd(); + new FlagCommand(); new Target(); new DebugFixFlags(); new Move(); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Captions.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Captions.java index f9ad2aa2d..4f4596a78 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Captions.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Captions.java @@ -529,6 +529,8 @@ public enum Captions implements Caption { FLAG_ADDED("$4Successfully added flag", "Flag"), FLAG_TUTORIAL_USAGE("$1Have an admin set the flag: $2%s", "CommandConfig"), FLAG_LIST_ENTRY("$2%s: $1%s", "Flag"), + FLAG_LIST_SEE_INFO("Click to view information about the flag", "Flag"), + FLAG_PARSE_EXCEPTION("$2Failed to parse flag '%s', value '%s': %s", "Flag"), // // FLAG_INFO_COLOR_KEY("$1", "Flag"), diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java index e6018aa39..e1bf0fc1d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java @@ -1107,10 +1107,20 @@ public class Plot { * @param flag the flag to remove * @return success */ - public boolean removeFlag(Class> flag) { + public boolean removeFlag(Class flag) { return FlagManager.removePlotFlag(this, flag); } + /** + * Remove a flag from this plot + * + * @param flag the flag to remove + * @return success + */ + public boolean removeFlag(PlotFlag flag) { + return this.removeFlag(flag.getClass()); + } + /** * Delete a plot (use null for the runnable if you don't need to be notified on completion) * diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/helpmenu/HelpMenu.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/helpmenu/HelpMenu.java index c10d9507b..107f12f93 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/helpmenu/HelpMenu.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/helpmenu/HelpMenu.java @@ -26,6 +26,11 @@ public class HelpMenu { return this; } + public HelpMenu setCommands(final List commands) { + this.commands = commands; + return this; + } + public HelpMenu getCommands() { this.commands = MainCommand.getInstance().getCommands(this.commandCategory, this.commandCaller);