diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear2DBlockPattern.java b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear2DBlockPattern.java index 5442510f9..0bed3a376 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear2DBlockPattern.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear2DBlockPattern.java @@ -10,14 +10,18 @@ import com.sk89q.worldedit.world.block.BaseBlock; public class Linear2DBlockPattern extends AbstractPattern { private final Pattern[] patternsArray; + private final int xScale; + private final int zScale; - public Linear2DBlockPattern(Pattern[] patterns) { + public Linear2DBlockPattern(Pattern[] patterns, int xScale, int zScale) { this.patternsArray = patterns; + this.xScale = xScale; + this.zScale = zScale; } @Override public BaseBlock apply(BlockVector3 position) { - int index = (position.getBlockX() + position.getBlockZ()) % patternsArray.length; + int index = (position.getBlockX() / this.xScale + position.getBlockZ() / this.zScale) % patternsArray.length; if (index < 0) { index += patternsArray.length; } @@ -26,7 +30,7 @@ public class Linear2DBlockPattern extends AbstractPattern { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - int index = (get.getBlockX() + get.getBlockZ()) % patternsArray.length; + int index = (get.getBlockX() / this.xScale + get.getBlockZ() / this.zScale) % patternsArray.length; if (index < 0) { index += patternsArray.length; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java index cbf7d0002..9f70debe9 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java @@ -10,14 +10,21 @@ import com.sk89q.worldedit.world.block.BaseBlock; public class Linear3DBlockPattern extends AbstractPattern { private final Pattern[] patternsArray; + private final int xScale; + private final int yScale; + private final int zScale; - public Linear3DBlockPattern(Pattern[] patterns) { + public Linear3DBlockPattern(Pattern[] patterns, int xScale, int yScale, int zScale) { this.patternsArray = patterns; + this.xScale = xScale; + this.yScale = yScale; + this.zScale = zScale; } @Override public BaseBlock apply(BlockVector3 position) { - int index = (position.getBlockX() + position.getBlockY() + position.getBlockZ()) % patternsArray.length; + int index = (position.getBlockX() / this.xScale + + position.getBlockY() / this.yScale + position.getBlockZ() / this.zScale) % patternsArray.length; if (index < 0) { index += patternsArray.length; } @@ -26,7 +33,8 @@ public class Linear3DBlockPattern extends AbstractPattern { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - int index = (get.getBlockX() + get.getBlockY() + get.getBlockZ()) % patternsArray.length; + int index = (get.getBlockX() / this.xScale + + get.getBlockY() / this.yScale + get.getBlockZ() / this.zScale) % patternsArray.length; if (index < 0) { index += patternsArray.length; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java index 87ea41d68..28bbea434 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/SuggestionHelper.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.command.util; +import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.NamespacedRegistry; import com.sk89q.worldedit.registry.Registry; @@ -35,6 +36,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; import static org.enginehub.piston.converter.SuggestionHelper.byPrefix; @@ -173,4 +175,57 @@ public final class SuggestionHelper { Predicate search = byPrefix(input.toLowerCase(Locale.ROOT)); return registry.keySet().stream().filter(search); } + + /** + * Returns a stream of suggestions for positive doubles. + * + * @param argumentInput the given input to filter with. + * @return a stream of suggestions. + */ + public static Stream suggestPositiveDoubles(String argumentInput) { + if (argumentInput.isEmpty()) { + return Stream.of("1", "2", "3", "4", "5", "6", "7", "8", "9"); + } + // if already a valid number, suggest more digits + if (isDouble(argumentInput)) { + Stream numbers = Stream.of("", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); + if (argumentInput.indexOf('.') == -1) { + numbers = Stream.concat(numbers, Stream.of(".")); + } + return numbers.map(s -> argumentInput + s); + } + // no valid input anymore + return Stream.empty(); + } + + /** + * Returns a stream of suggestions for positive integers. + * + * @param argumentInput the given input to filter with. + * @return a stream of suggestions. + */ + public static Stream suggestPositiveIntegers(String argumentInput) { + if (argumentInput.isEmpty()) { + return IntStream.rangeClosed(1, 9).mapToObj(Integer::toString); + } + if (MathMan.isInteger(argumentInput)) { + return IntStream.rangeClosed(0, 9).mapToObj(Integer::toString).map(s -> argumentInput + s); + } + // no valid input anymore + return Stream.empty(); + } + + private static boolean isDouble(String input) { + boolean point = false; + for (char c : input.toCharArray()) { + if (!Character.isDigit(c)) { + if (c == '.' && !point) { + point = true; + } else { + return false; + } + } + } + return true; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java index e8bad9814..3a392b8d8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java @@ -22,7 +22,11 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.factory.parser.pattern.BiomePatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.BufferedPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.ExistingPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.Linear2DPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.Linear3DPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.PerlinPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser; @@ -66,6 +70,10 @@ public final class PatternFactory extends AbstractFactory { register(new PerlinPatternParser(worldEdit)); register(new RidgedMultiFractalPatternParser(worldEdit)); register(new BiomePatternParser(worldEdit)); + register(new Linear2DPatternParser(worldEdit)); + register(new Linear3DPatternParser(worldEdit)); + register(new BufferedPatternParser(worldEdit)); + register(new ExistingPatternParser(worldEdit)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/RichParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/RichParser.java index 66fe34d98..fae4b740d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/RichParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/RichParser.java @@ -1,5 +1,6 @@ package com.sk89q.worldedit.extension.factory.parser; +import com.google.common.base.Preconditions; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; @@ -7,8 +8,10 @@ import com.sk89q.worldedit.internal.registry.InputParser; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import java.util.StringJoiner; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Stream; /** @@ -18,51 +21,75 @@ import java.util.stream.Stream; * @param the parse result. */ public abstract class RichParser extends InputParser { - private final String prefix; - private final String required; + private final String[] prefixes; /** * Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}. * * @param worldEdit the worldedit instance. - * @param prefix the prefix of this parser result. + * @param aliases the prefix of this parser result. */ - protected RichParser(WorldEdit worldEdit, String prefix) { + protected RichParser(WorldEdit worldEdit, String... aliases) { super(worldEdit); - this.prefix = prefix; - this.required = prefix + "["; + Preconditions.checkArgument(aliases.length >= 1, "Aliases may not be empty"); + this.prefixes = aliases; + } + + @NotNull + private static Predicate validPrefix(String other) { + return prefix -> { + if (prefix.length() > other.length()) { + return prefix.startsWith(other); + } + return other.startsWith(prefix); + }; + } + + @NotNull + private Function> extractArguments(String input) { + return prefix -> { + if (input.length() > prefix.length()) { + // input already contains argument(s) -> extract them + String[] strings = extractArguments(input.substring(prefix.length()), false); + // rebuild the argument string without the last argument + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < strings.length - 1; i++) { + builder.append('[').append(strings[i]).append(']'); + } + String previous = prefix + builder; + // read the suggestions for the last argument + return getSuggestions(strings[strings.length - 1], strings.length - 1) + .map(suggestion -> previous + "[" + suggestion); + } else { + return Stream.of(prefix); + } + }; + } + + public String getPrefix() { + return this.prefixes[0]; } @Override public Stream getSuggestions(String input) { - // we don't even want to start suggesting if it's not meant to be this parser result - if (input.length() >= this.required.length() && !input.startsWith(this.required)) { - return Stream.empty(); - } - // suggest until the first [ as long as it isn't fully typed - if (input.length() < this.required.length()) { - return Stream.of(this.required).filter(s -> s.startsWith(input)); - } - // we know that it is at least "" - String[] strings = extractArguments(input.substring(this.prefix.length()), false); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < strings.length - 1; i++) { - builder.append('[').append(strings[i]).append(']'); - } - String previous = this.prefix + builder; - return getSuggestions(strings[strings.length - 1], strings.length - 1).map(s -> previous + "[" + s + "]"); + return Arrays.stream(this.prefixes) + .filter(validPrefix(input)) + .flatMap(extractArguments(input)); } @Override public E parseFromInput(String input, ParserContext context) throws InputParseException { - if (!input.startsWith(this.prefix)) { - return null; + for (String prefix : this.prefixes) { + if (!input.startsWith(prefix)) { + continue; + } + if (input.length() < prefix.length()) { + continue; + } + String[] arguments = extractArguments(input.substring(prefix.length()), true); + return parseFromInput(arguments, context); } - if (input.length() < this.prefix.length()) { - return null; - } - String[] arguments = extractArguments(input.substring(prefix.length()), true); - return parseFromInput(arguments, context); + return null; } /** @@ -118,40 +145,4 @@ public abstract class RichParser extends InputParser { } return arguments.toArray(new String[0]); } - - /** - * Returns a stream of suggestions for positive doubles. - * - * @param argumentInput the given input to filter with. - * @return a stream of suggestions. - */ - protected Stream suggestPositiveDoubles(String argumentInput) { - if (argumentInput.isEmpty()) { - return Stream.of("1", "2", "3", "4", "5", "6", "7", "8", "9"); - } - // if already a valid number, suggest more digits - if (isDouble(argumentInput)) { - Stream numbers = Stream.of("", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); - if (argumentInput.indexOf('.') == -1) { - numbers = Stream.concat(numbers, Stream.of(".")); - } - return numbers.map(s -> argumentInput + s); - } - // no valid input anymore - return Stream.empty(); - } - - private static boolean isDouble(String input) { - boolean point = false; - for (char c : input.toCharArray()) { - if (!Character.isDigit(c)) { - if (c == '.' && !point) { - point = true; - } else { - return false; - } - } - } - return true; - } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AdjacentMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AdjacentMaskParser.java index c9d24e1a8..d60ef0d9a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AdjacentMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AdjacentMaskParser.java @@ -3,6 +3,7 @@ package com.sk89q.worldedit.extension.factory.parser.mask; import com.boydti.fawe.object.mask.AdjacentAnyMask; import com.boydti.fawe.object.mask.AdjacentMask; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.factory.parser.RichParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; @@ -22,7 +23,7 @@ public class AdjacentMaskParser extends RichParser { if (index == 0) { return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); } else if (index == 1 || index == 2) { - return this.suggestPositiveDoubles(argumentInput); + return SuggestionHelper.suggestPositiveDoubles(argumentInput); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AngleMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AngleMaskParser.java index 0c7acf214..f2d9867ee 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AngleMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AngleMaskParser.java @@ -2,10 +2,13 @@ package com.sk89q.worldedit.extension.factory.parser.mask; import com.boydti.fawe.object.mask.AngleMask; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.factory.parser.RichParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.jetbrains.annotations.NotNull; import java.util.stream.Stream; @@ -21,7 +24,7 @@ public class AngleMaskParser extends RichParser { @Override protected Stream getSuggestions(String argumentInput, int index) { if (index == 0 || index == 1) { - return suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); + return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { return Stream.of(flags); } @@ -37,7 +40,7 @@ public class AngleMaskParser extends RichParser { String maxArg = arguments[1]; boolean degree = minArg.endsWith("d"); if (degree ^ maxArg.endsWith("d")) { - throw new InputParseException("Cannot combine degree with block-step"); + throw new InputParseException(TranslatableComponent.of("fawe.error.mask.angle")); } boolean overlay = false; if (arguments.length > 2) { @@ -46,7 +49,8 @@ public class AngleMaskParser extends RichParser { if (flag.equals("-o")) { overlay = true; } else { - throw new InputParseException("The flag " + flag + " is not applicable for this mask!"); + throw new InputParseException(TranslatableComponent.of("fawe.error.invalid-flag", + TextComponent.of(flag))); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExtremaMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExtremaMaskParser.java index 50fa9b849..479b6f71c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExtremaMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExtremaMaskParser.java @@ -2,10 +2,13 @@ package com.sk89q.worldedit.extension.factory.parser.mask; import com.boydti.fawe.object.mask.ExtremaMask; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.factory.parser.RichParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.jetbrains.annotations.NotNull; import java.util.stream.Stream; @@ -21,7 +24,7 @@ public class ExtremaMaskParser extends RichParser { @Override protected Stream getSuggestions(String argumentInput, int index) { if (index == 0 || index == 1) { - return suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); + return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { return Stream.of(flags); } @@ -37,7 +40,7 @@ public class ExtremaMaskParser extends RichParser { String maxArg = arguments[1]; boolean degree = minArg.endsWith("d"); if (degree ^ maxArg.endsWith("d")) { - throw new InputParseException("Cannot combine degree with block-step"); + throw new InputParseException(TranslatableComponent.of("fawe.error.mask.angle")); } double min; double max; @@ -48,7 +51,8 @@ public class ExtremaMaskParser extends RichParser { if (flag.equals("-o")) { overlay = true; } else { - throw new InputParseException("The flag " + flag + " is not applicable for this mask!"); + throw new InputParseException(TranslatableComponent.of("fawe.error.invalid-flag", + TextComponent.of(flag))); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ROCAngleMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ROCAngleMaskParser.java index fd4672ae7..b99274084 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ROCAngleMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ROCAngleMaskParser.java @@ -2,10 +2,13 @@ package com.sk89q.worldedit.extension.factory.parser.mask; import com.boydti.fawe.object.mask.ROCAngleMask; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.factory.parser.RichParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.jetbrains.annotations.NotNull; import java.util.stream.Stream; @@ -21,7 +24,7 @@ public class ROCAngleMaskParser extends RichParser { @Override protected Stream getSuggestions(String argumentInput, int index) { if (index == 0 || index == 1) { - return suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); + return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { return Stream.of(flags); } @@ -37,7 +40,7 @@ public class ROCAngleMaskParser extends RichParser { String maxArg = arguments[1]; boolean degree = minArg.endsWith("d"); if (degree ^ maxArg.endsWith("d")) { - throw new InputParseException("Cannot combine degree with block-step"); + throw new InputParseException(TranslatableComponent.of("fawe.error.mask.angle")); } double min; double max; @@ -48,7 +51,8 @@ public class ROCAngleMaskParser extends RichParser { if (flag.equals("-o")) { overlay = true; } else { - throw new InputParseException("The flag " + flag + " is not applicable for this mask!"); + throw new InputParseException(TranslatableComponent.of("fawe.error.invalid-flag", + TextComponent.of(flag))); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RadiusMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RadiusMaskParser.java index 914159218..ae0f7182e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RadiusMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RadiusMaskParser.java @@ -2,6 +2,7 @@ package com.sk89q.worldedit.extension.factory.parser.mask; import com.boydti.fawe.object.mask.RadiusMask; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.factory.parser.RichParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; @@ -19,7 +20,7 @@ public class RadiusMaskParser extends RichParser { @Override protected Stream getSuggestions(String argumentInput, int index) { if (index == 0 || index == 1) { - return suggestPositiveDoubles(argumentInput); + return SuggestionHelper.suggestPositiveDoubles(argumentInput); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SimplexMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SimplexMaskParser.java index 09424b6c8..4e96690f0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SimplexMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SimplexMaskParser.java @@ -2,6 +2,7 @@ package com.sk89q.worldedit.extension.factory.parser.mask; import com.boydti.fawe.object.mask.SimplexMask; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.factory.parser.RichParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; @@ -20,7 +21,7 @@ public class SimplexMaskParser extends RichParser { @Override protected Stream getSuggestions(String argumentInput, int index) { if (index < 3) { - suggestPositiveDoubles(argumentInput); + return SuggestionHelper.suggestPositiveDoubles(argumentInput); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/BufferedPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/BufferedPatternParser.java new file mode 100644 index 000000000..d7e48ccf8 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/BufferedPatternParser.java @@ -0,0 +1,43 @@ +package com.sk89q.worldedit.extension.factory.parser.pattern; + +import com.boydti.fawe.object.pattern.BufferedPattern; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.factory.parser.RichParser; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import org.jetbrains.annotations.NotNull; + +import java.util.stream.Stream; + +public class BufferedPatternParser extends RichParser { + + /** + * Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}. + * + * @param worldEdit the worldedit instance. + */ + public BufferedPatternParser(WorldEdit worldEdit) { + super(worldEdit, "#buffer"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + if (index == 0) { + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + } + return Stream.empty(); + } + + @Override + protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if (arguments.length != 1) { + throw new InputParseException(TranslatableComponent.of("fawe.error.command.syntax", + TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])"))); + } + Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context); + return new BufferedPattern(context.requireActor(), inner); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/ExistingPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/ExistingPatternParser.java new file mode 100644 index 000000000..f69981b9a --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/ExistingPatternParser.java @@ -0,0 +1,29 @@ +package com.sk89q.worldedit.extension.factory.parser.pattern; + +import com.boydti.fawe.object.pattern.ExistingPattern; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; + +import java.util.Collections; +import java.util.List; + +public class ExistingPatternParser extends SimpleInputParser { + private final List aliases = Collections.singletonList("#existing"); + + public ExistingPatternParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return this.aliases; + } + + @Override + public Pattern parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + return new ExistingPattern(context.requireExtent()); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/Linear2DPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/Linear2DPatternParser.java new file mode 100644 index 000000000..34922b994 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/Linear2DPatternParser.java @@ -0,0 +1,71 @@ +package com.sk89q.worldedit.extension.factory.parser.pattern; + +import com.boydti.fawe.object.pattern.Linear2DBlockPattern; +import com.google.common.base.Preconditions; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; +import com.sk89q.worldedit.extension.factory.parser.RichParser; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.function.pattern.RandomPattern; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; +import java.util.stream.Stream; + +public class Linear2DPatternParser extends RichParser { + + /** + * Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}. + * + * @param worldEdit the worldedit instance. + */ + public Linear2DPatternParser(WorldEdit worldEdit) { + super(worldEdit, "#linear2d", "#l2d"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + switch (index) { + case 0: + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 1: + case 2: + return SuggestionHelper.suggestPositiveIntegers(argumentInput); + default: + return Stream.empty(); + } + } + + @Override + protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if (arguments.length == 0 || arguments.length > 3) { + throw new InputParseException(TranslatableComponent.of("fawe.error.command.syntax", + TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])"))); + } + Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context); + if (inner instanceof BlockStateHolder) { + return inner; + } + int xScale = 1; + int zScale = 1; + if (arguments.length > 1) { + xScale = Integer.parseInt(arguments[1]); + Preconditions.checkArgument(xScale != 0); + } + if (arguments.length > 2) { + zScale = Integer.parseInt(arguments[2]); + Preconditions.checkArgument(zScale != 0); + } + if (inner instanceof RandomPattern) { + Set patterns = ((RandomPattern) inner).getPatterns(); + return new Linear2DBlockPattern(patterns.toArray(new Pattern[0]), xScale, zScale); + } + throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName() + + " cannot be used with " + getPrefix())); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/Linear3DPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/Linear3DPatternParser.java new file mode 100644 index 000000000..72b8480ea --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/Linear3DPatternParser.java @@ -0,0 +1,77 @@ +package com.sk89q.worldedit.extension.factory.parser.pattern; + +import com.boydti.fawe.object.pattern.Linear3DBlockPattern; +import com.google.common.base.Preconditions; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; +import com.sk89q.worldedit.extension.factory.parser.RichParser; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.function.pattern.RandomPattern; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; +import java.util.stream.Stream; + +public class Linear3DPatternParser extends RichParser { + + /** + * Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}. + * + * @param worldEdit the worldedit instance. + */ + public Linear3DPatternParser(WorldEdit worldEdit) { + super(worldEdit, "#linear3d", "#l3d"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + switch (index) { + case 0: + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 1: + case 2: + case 3: + return SuggestionHelper.suggestPositiveIntegers(argumentInput); + default: + return Stream.empty(); + } + } + + @Override + protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if (arguments.length == 0 || arguments.length > 4) { + throw new InputParseException(TranslatableComponent.of("fawe.error.command.syntax", + TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])"))); + } + Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context); + if (inner instanceof BlockStateHolder) { + return inner; + } + int xScale = 1; + int yScale = 1; + int zScale = 1; + if (arguments.length > 1) { + xScale = Integer.parseInt(arguments[1]); + Preconditions.checkArgument(xScale != 0); + } + if (arguments.length > 2) { + yScale = Integer.parseInt(arguments[2]); + Preconditions.checkArgument(yScale != 0); + } + if (arguments.length > 3) { + zScale = Integer.parseInt(arguments[3]); + Preconditions.checkArgument(zScale != 0); + } + if (inner instanceof RandomPattern) { + Set patterns = ((RandomPattern) inner).getPatterns(); + return new Linear3DBlockPattern(patterns.toArray(new Pattern[0]), xScale, yScale,zScale); + } + throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName() + + " cannot be used with " + getPrefix())); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/NoisePatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/NoisePatternParser.java index e8b2a0e30..d9b0ee56a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/NoisePatternParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/NoisePatternParser.java @@ -2,12 +2,15 @@ package com.sk89q.worldedit.extension.factory.parser.pattern; import com.boydti.fawe.object.random.NoiseRandom; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.factory.parser.RichParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.RandomPattern; import com.sk89q.worldedit.math.noise.NoiseGenerator; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.block.BlockStateHolder; import org.jetbrains.annotations.NotNull; @@ -35,7 +38,7 @@ public abstract class NoisePatternParser extends RichParser { @Override protected Stream getSuggestions(String argumentInput, int index) { if (index == 0) { - return suggestPositiveDoubles(argumentInput); + return SuggestionHelper.suggestPositiveDoubles(argumentInput); } if (index == 1) { return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); @@ -46,8 +49,8 @@ public abstract class NoisePatternParser extends RichParser { @Override protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) { if (arguments.length != 2) { - throw new InputParseException(this.name + " requires a scale and a pattern, e.g. #" - + this.name + "[5][dirt,stone]"); + throw new InputParseException(TranslatableComponent.of("fawe.error.command.syntax", + TextComponent.of(getPrefix() + "[scale][pattern] (e.g. " + getPrefix() + "[5][dirt,stone])"))); } double scale = parseScale(arguments[0]); Pattern inner = worldEdit.getPatternFactory().parseFromInput(arguments[1], context); @@ -56,8 +59,8 @@ public abstract class NoisePatternParser extends RichParser { } else if (inner instanceof BlockStateHolder) { return inner; // single blocks won't have any impact on how a noise behaves } else { - throw new InputParseException("Pattern " + inner.getClass().getSimpleName() - + " cannot be used with #" + this.name); + throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName() + + " cannot be used with #" + this.name)); } } diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index b86e09a95..de060a1ed 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -102,6 +102,8 @@ "fawe.error.player.not.found": "Player not found: {0}", "fawe.error.worldedit.some.fails": "{0} blocks weren't placed because they were outside your allowed region.", "fawe.error.worldedit.some.fails.blockbag": "Missing blocks: {0}", + "fawe.error.mask.angle": "Cannot combine degree with block-step", + "fawe.error.invalid-flag": "The flag {0} is not applicable here", "fawe.cancel.worldedit.cancel.count": "Cancelled {0} edits.", "fawe.cancel.worldedit.cancel.reason.confirm": "Use //confirm to execute {2}",