diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCmd.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCmd.java index bfe3cc4c9..38cf40664 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCmd.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/FlagCmd.java @@ -6,11 +6,12 @@ import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.config.Settings; import com.github.intellectualsites.plotsquared.plot.database.DBFunc; import com.github.intellectualsites.plotsquared.plot.flag.BlockStateListFlag; -import com.github.intellectualsites.plotsquared.plot.flag.Flag; import com.github.intellectualsites.plotsquared.plot.flag.FlagManager; import com.github.intellectualsites.plotsquared.plot.flag.Flags; -import com.github.intellectualsites.plotsquared.plot.flag.IntegerFlag; -import com.github.intellectualsites.plotsquared.plot.flag.ListFlag; +import com.github.intellectualsites.plotsquared.plot.flags.GlobalFlagContainer; +import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; +import com.github.intellectualsites.plotsquared.plot.flags.types.BlockTypeListFlag; +import com.github.intellectualsites.plotsquared.plot.flags.types.IntegerFlag; import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; @@ -37,7 +38,7 @@ import java.util.Set; "setflag"}, usage = "/plot flag ", description = "Set plot flags", category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, permission = "plots.flag") public class FlagCmd extends SubCommand { - private boolean checkPermValue(PlotPlayer player, Flag flag, String key, String value) { + private boolean checkPermValue(PlotPlayer player, PlotFlag flag, String key, String value) { key = key.toLowerCase(); value = value.toLowerCase(); String perm = Captions @@ -62,20 +63,24 @@ public class FlagCmd extends SubCommand { } catch (NumberFormatException ignore) { } - } else if (flag instanceof BlockStateListFlag) { - final BlockStateListFlag blockListFlag = (BlockStateListFlag) flag; - Set parsedBlocks = blockListFlag.parseValue(value); - for (final BlockType block : parsedBlocks) { - final String permission = Captions - .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), - key.toLowerCase(), block.toString().toLowerCase()); - final boolean result = Permissions.hasPermission(player, permission); - if (!result) { - MainUtil.sendMessage(player, Captions.NO_PERMISSION, Captions + } else if (flag instanceof BlockTypeListFlag) { + final BlockTypeListFlag blockListFlag = (BlockTypeListFlag) flag; + try { + List parsedBlocks = blockListFlag.parse(value); + for (final BlockType block : parsedBlocks) { + final String permission = Captions .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), - key.toLowerCase(), value.toLowerCase())); - return false; + key.toLowerCase(), block.toString().toLowerCase()); + final boolean result = Permissions.hasPermission(player, permission); + if (!result) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, Captions + .format(Captions.PERMISSION_SET_FLAG_KEY_VALUE.getTranslated(), + key.toLowerCase(), value.toLowerCase())); + return false; + } } + } catch (final Exception e) { + return false; } return true; } @@ -117,13 +122,13 @@ public class FlagCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_SET_FLAG_OTHER); return false; } - Flag flag = null; + PlotFlag flag = null; if (args.length > 1) { - flag = FlagManager.getFlag(args[1]); + flag = GlobalFlagContainer.getInstance().getFlagFromString(args[1]); if (flag == null || flag.isReserved()) { boolean suggested = false; try { - StringComparison> stringComparison = + StringComparison> stringComparison = new StringComparison<>(args[1], Flags.getFlags()); String best = stringComparison.getBestMatch(); if (best != null) { 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 239de4e59..808fd85e5 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 @@ -548,6 +548,9 @@ public enum Captions { FLAG_CATEGORY_BOOLEAN("Boolean Flags", "Flags"), FLAG_CATEGORY_MIXED("Mixed Value Flags", "Flags"), // + // + FLAG_DESCRIPTION_EXPLOSION("Set to 'true' to enable explosions in the plot, and 'false' to disable them", "Flags"), + // // FLAG_ERROR_BOOLEAN("Flag value must be a boolean (true|false)", "Flags"), FLAG_ERROR_ENUM("Must be one of: %s", "Flags"), @@ -558,6 +561,7 @@ public enum Captions { FLAG_ERROR_KEEP("Flag value must be a timestamp or a boolean", "Flags"), FLAG_ERROR_LONG("Flag value must be a whole number (large numbers allowed)", "Flags"), FLAG_ERROR_PLOTBLOCKLIST("Flag value must be a block list", "Flags"), + FLAG_ERROR_INVALID_BLOCK("The provided value is not a valid block", "Flags"), FLAG_ERROR_PRICE("Flag value must be a positive number.", "Flags"), FLAG_ERROR_STRING("Flag value must be alphanumeric. Some special characters are allowed.", "Flags"), FLAG_ERROR_STRINGLIST("Flag value must be a string list", "Flags"), diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagContainer.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagContainer.java index 28d09ec73..979c47743 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagContainer.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagContainer.java @@ -50,6 +50,18 @@ import java.util.Map; return this; } + public PlotFlag getFlagErased(Class flagClass) { + final PlotFlag flag = this.flagMap.get(flagClass); + if (flag != null) { + return flag; + } else { + if (getParentContainer() != null) { + return getParentContainer().getFlagErased(flagClass); + } + } + return null; + } + public PlotFlag getFlag(final Class> flagClass) { final PlotFlag flag = this.flagMap.get(flagClass); if (flag != null) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagParseException.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagParseException.java index 98d6ee607..e49ac92dd 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagParseException.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/FlagParseException.java @@ -1,15 +1,19 @@ package com.github.intellectualsites.plotsquared.plot.flags; +import com.github.intellectualsites.plotsquared.plot.config.Captions; + public class FlagParseException extends Exception { private final PlotFlag flag; private final String value; + private final Captions errorMessage; - public FlagParseException(final PlotFlag flag, final String value) { + public FlagParseException(final PlotFlag flag, final String value, final Captions errorMessage) { super(String.format("Failed to parse flag of type '%s'. Value '%s' was not accepted.", flag.getName(), value)); this.flag = flag; this.value = value; + this.errorMessage = errorMessage; } /** @@ -30,4 +34,7 @@ public class FlagParseException extends Exception { return this.flag; } + public Captions getErrorMessage() { + return errorMessage; + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java index 8cbfa728f..97a251ed0 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/GlobalFlagContainer.java @@ -4,11 +4,26 @@ import com.github.intellectualsites.plotsquared.plot.flags.implementations.Explo import lombok.Getter; import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; public final class GlobalFlagContainer extends FlagContainer { @Getter private static final GlobalFlagContainer instance = new GlobalFlagContainer(); + private final Map> stringClassMap = new HashMap<>(); + + @Override public PlotFlag getFlagErased(Class flagClass) { + final PlotFlag flag = super.getFlagErased(flagClass); + if (flag != null) { + return flag; + } else { + throw new IllegalStateException(String.format("Unrecognized flag '%s'. All flag types" + + " must be present in the global flag container.", flagClass.getSimpleName())); + } + } + @Nonnull @Override public PlotFlag getFlag(Class> flagClass) { final PlotFlag flag = super.getFlag(flagClass); if (flag != null) { @@ -25,4 +40,21 @@ public final class GlobalFlagContainer extends FlagContainer { this.addFlag(new ExplosionFlag()); } + @Override public void addFlag(PlotFlag flag) { + super.addFlag(flag); + this.stringClassMap.put(flag.getName().toLowerCase(Locale.ENGLISH), flag.getClass()); + } + + public Class getFlagClassFromString(final String name) { + return this.stringClassMap.get(name.toLowerCase(Locale.ENGLISH)); + } + + public PlotFlag getFlagFromString(final String name) { + final Class flagClass = this.getFlagClassFromString(name); + if (flagClass == null) { + return null; + } + return getFlagErased(flagClass); + } + } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/PlotFlag.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/PlotFlag.java index a07745891..cab89b4f8 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/PlotFlag.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/PlotFlag.java @@ -1,9 +1,12 @@ package com.github.intellectualsites.plotsquared.plot.flags; +import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.google.common.base.Preconditions; import lombok.EqualsAndHashCode; import org.jetbrains.annotations.NotNull; +import java.util.Locale; + /** * A plot flag is any property that can be assigned * to a plot, that will alter its functionality in some way. @@ -14,14 +17,19 @@ import org.jetbrains.annotations.NotNull; @EqualsAndHashCode(of = "value") public abstract class PlotFlag { private T value; + private final Captions flagCategory; + private final Captions flagDescription; /** * Construct a new flag instance. * * @param value Flag value */ - protected PlotFlag(@NotNull final T value) { - this.value = Preconditions.checkNotNull(value, "flag values may not be null"); + protected PlotFlag(@NotNull final T value, @NotNull final Captions flagCategory, + @NotNull final Captions flagDescription) { + this.value = Preconditions.checkNotNull(value, "flag value may not be null"); + this.flagCategory = Preconditions.checkNotNull(flagCategory, "flag category may not be null"); + this.flagDescription = Preconditions.checkNotNull(flagDescription, "flag description may not be null"); } /** @@ -72,7 +80,17 @@ import org.jetbrains.annotations.NotNull; public abstract String toString(); public final String getName() { - return this.getClass().getSimpleName(); + return this.getClass().getSimpleName().toLowerCase(Locale.ENGLISH); } + public Captions getFlagDescription() { + return this.flagDescription; + } + + public Captions getFlagCategory() { + return this.flagCategory; + } + + public abstract String getExample(); + } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/implementations/ExplosionFlag.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/implementations/ExplosionFlag.java index 362cb7d65..616fbe131 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/implementations/ExplosionFlag.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/implementations/ExplosionFlag.java @@ -1,6 +1,16 @@ package com.github.intellectualsites.plotsquared.plot.flags.implementations; +import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.flags.types.BooleanFlag; public class ExplosionFlag extends BooleanFlag { + + public ExplosionFlag() { + super(Captions.FLAG_DESCRIPTION_EXPLOSION); + } + + @Override public String getExample() { + return "true"; + } + } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/BlockTypeListFlag.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/BlockTypeListFlag.java new file mode 100644 index 000000000..dc7ce81c5 --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/BlockTypeListFlag.java @@ -0,0 +1,40 @@ +package com.github.intellectualsites.plotsquared.plot.flags.types; + +import com.github.intellectualsites.plotsquared.plot.config.Captions; +import com.github.intellectualsites.plotsquared.plot.flags.FlagParseException; +import com.github.intellectualsites.plotsquared.plot.util.world.BlockUtil; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class BlockTypeListFlag extends ListFlag { + + public BlockTypeListFlag(Captions description) { + super(Captions.FLAG_CATEGORY_BLOCK_LIST, description); + } + + @Override public List parse(@NotNull String input) throws FlagParseException { + final List parsedBlocks = new ArrayList<>(); + final String[] split = input.split(",(?![^\\(\\[]*[\\]\\)])"); + if (split.length == 0) { + return parsedBlocks; + } + for (final String blockString : split) { + final BlockState blockState = BlockUtil.get(blockString); + if (blockState == null) { + throw new FlagParseException(this, blockString, Captions.FLAG_ERROR_INVALID_BLOCK); + } else { + parsedBlocks.add(blockState.getBlockType()); + } + } + return parsedBlocks; + } + + @Override public String getExample() { + return "air,grass_block"; + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/BooleanFlag.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/BooleanFlag.java index f92e129cf..02d33257d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/BooleanFlag.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/BooleanFlag.java @@ -1,5 +1,6 @@ package com.github.intellectualsites.plotsquared.plot.flags.types; +import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.flags.FlagParseException; import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; import org.jetbrains.annotations.NotNull; @@ -17,26 +18,29 @@ public abstract class BooleanFlag extends PlotFlag { * Construct a new flag instance. * * @param value Flag value + * @param description Flag description */ - protected BooleanFlag(boolean value) { - super(value); + protected BooleanFlag(final boolean value, final Captions description) { + super(value, Captions.FLAG_CATEGORY_BOOLEAN, description); } /** * Construct a new boolean flag, with * {@code false} as the default value. + * + * @param description Flag description */ - protected BooleanFlag() { - this(false); + protected BooleanFlag(final Captions description) { + this(false, description); } @Override public Boolean parse(@NotNull String input) throws FlagParseException { if (positiveValues.contains(input.toLowerCase(Locale.ENGLISH))) { - return this.setFlagValue(true); + return true; } else if (negativeValues.contains(input.toLowerCase(Locale.ENGLISH))) { - return this.setFlagValue(false); + return false; } else { - throw new FlagParseException(this, input); + throw new FlagParseException(this, input, Captions.FLAG_ERROR_BOOLEAN); } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/IntegerFlag.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/IntegerFlag.java new file mode 100644 index 000000000..b11a27e33 --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/IntegerFlag.java @@ -0,0 +1,38 @@ +package com.github.intellectualsites.plotsquared.plot.flags.types; + +import com.github.intellectualsites.plotsquared.plot.config.Captions; +import com.github.intellectualsites.plotsquared.plot.flags.FlagParseException; +import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; +import org.jetbrains.annotations.NotNull; + +public class IntegerFlag extends PlotFlag { + + protected IntegerFlag(final int defaultValue, @NotNull Captions flagDescription) { + super(defaultValue, Captions.FLAG_CATEGORY_INTEGERS, flagDescription); + } + + protected IntegerFlag(@NotNull Captions flagDescription) { + this(0, flagDescription); + } + + @Override public Integer parse(@NotNull String input) throws FlagParseException { + try { + return Integer.parseInt(input); + } catch (final Throwable throwable) { + throw new FlagParseException(this, input, Captions.FLAG_ERROR_INTEGER); + } + } + + @Override public Integer merge(@NotNull Integer oldValue, @NotNull Integer newValue) { + return oldValue + newValue; + } + + @Override public String toString() { + return this.getValue().toString(); + } + + @Override public String getExample() { + return "10"; + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/ListFlag.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/ListFlag.java new file mode 100644 index 000000000..3089f893e --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flags/types/ListFlag.java @@ -0,0 +1,27 @@ +package com.github.intellectualsites.plotsquared.plot.flags.types; + +import com.github.intellectualsites.plotsquared.plot.config.Captions; +import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; +import com.github.intellectualsites.plotsquared.plot.util.StringMan; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public abstract class ListFlag extends PlotFlag> { + + public ListFlag(final Captions category, final Captions description) { + super(new ArrayList<>(), category, description); + } + + @Override public List merge(@NotNull List oldValue, @NotNull List newValue) { + final List mergedList = new ArrayList<>(); + mergedList.addAll(oldValue); + mergedList.addAll(newValue); + return this.setFlagValue(mergedList); + } + + @Override public String toString() { + return StringMan.join(this.getValue(), ","); + } +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/world/BlockUtil.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/world/BlockUtil.java index ca5b8f777..e4afd9c5d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/world/BlockUtil.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/world/BlockUtil.java @@ -18,9 +18,9 @@ import java.util.Map; public final class BlockUtil { private BlockUtil(){} - private static final ParserContext PARSER_CONTEXT = new ParserContext(); + private static ParserContext PARSER_CONTEXT = new ParserContext(); - private static final InputParser PARSER; + private static InputParser PARSER; static { PARSER_CONTEXT.setRestricted(false); @@ -29,15 +29,15 @@ public final class BlockUtil { PARSER = WorldEdit.getInstance().getBlockFactory().getParsers().get(0); } - public static final BlockState get(int id) { + public static BlockState get(int id) { return LegacyMapper.getInstance().getBlockFromLegacy(id); } - public static final BlockState get(int id, int data) { + public static BlockState get(int id, int data) { return LegacyMapper.getInstance().getBlockFromLegacy(id, data); } - public static final BlockState get(String id) { + public static BlockState get(String id) { if (id.length() == 1 && id.charAt(0) == '*') { return FuzzyBlockState.builder().type(BlockTypes.AIR).build(); } @@ -66,7 +66,7 @@ public final class BlockUtil { } } - public static final BlockState[] parse(String commaDelimited) { + public static BlockState[] parse(String commaDelimited) { String[] split = commaDelimited.split(",(?![^\\(\\[]*[\\]\\)])"); BlockState[] result = new BlockState[split.length]; for (int i = 0; i < split.length; i++) {