From 6807ccd960b3d761971ac74cb69d6f2081f04c2a Mon Sep 17 00:00:00 2001 From: IronApollo Date: Sun, 6 Sep 2020 18:42:43 -0400 Subject: [PATCH 1/2] Reimplement Masks + Fixes Masks Reimplemented: - Adjacent (~): Adjacent to a specific number of other blocks. - Example: ~[oak_log][1][4] - Extrema (#extrema): Restrict to near specific terrain extrema. The "-o" flag will only overlay existing terrain. - Example: #extrema[0d][45d][-o] - ROC Angle (#roc): Restrict to near specific terrain slope rate of change. The "-o" flag will only overlay existing terrain. - Example: #roc[0d][45d][-o] - Surface (#surface): Restrict to surfaces (any solid block touching air). - Example: #surface - Wall (#wall): Restrict to walls (any block n,e,s,w of air). - Example: #wall Other Changes: - Minor logic change to angle mask's overlay. - Fixed negating air mask. - Added overlay flag to angle (/) mask. --- .../fawe/object/mask/AdjacentAnyMask.java | 4 +- .../boydti/fawe/object/mask/AngleMask.java | 4 +- .../sk89q/worldedit/command/MaskCommands.java | 175 +----------------- .../extension/factory/MaskFactory.java | 36 ++-- .../parser/mask/AdjacentMaskParser.java | 45 +++++ .../factory/parser/mask/AngleMaskParser.java | 21 ++- .../parser/mask/ExtremaMaskParser.java | 64 +++++++ .../parser/mask/ROCAngleMaskParser.java | 64 +++++++ .../factory/parser/mask/RadiusMaskParser.java | 35 ++++ .../parser/mask/SurfaceMaskParser.java | 30 +++ .../factory/parser/mask/WallMaskParser.java | 31 ++++ .../worldedit/function/mask/BlockMask.java | 5 + 12 files changed, 307 insertions(+), 207 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AdjacentMaskParser.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExtremaMaskParser.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ROCAngleMaskParser.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RadiusMaskParser.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SurfaceMaskParser.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/WallMaskParser.java diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java index 8669fd33f..e0536347d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java @@ -1,8 +1,8 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.AbstractMask; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.MutableBlockVector3; @@ -14,7 +14,7 @@ public class AdjacentAnyMask extends AbstractMask implements ResettableMask { private final CachedMask mask; private final MutableBlockVector3 mutable; - public AdjacentAnyMask(AbstractExtentMask mask) { + public AdjacentAnyMask(Mask mask) { this.mask = CachedMask.cache(mask); mutable = new MutableBlockVector3(); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java index 5789190a8..f5f48d698 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java @@ -166,11 +166,9 @@ public class AngleMask extends SolidBlockMask implements ResettableMask { return false; } if (overlay) { - if (y < 255 && !mask.test(extent, x, y + 1, z)) { + if (y < 255 && !adjacentAir(extent, vector)) { return lastValue = false; } - } else if (!adjacentAir(extent, vector)) { - return false; } return testSlope(extent, x, y, z); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/MaskCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/MaskCommands.java index 773313b94..f4424f1dd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/MaskCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/MaskCommands.java @@ -65,18 +65,6 @@ // public MaskCommands(WorldEdit worldEdit) { // this.worldEdit = worldEdit; // } -// -// @Command( -// name = "#simplex", -// desc = "Use simplex noise as the mask" -// ) -// public Mask simplex(@Arg(desc = "double scale") double scale, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) { -// scale = 1d / Math.max(1, scale); -// minInt = (minInt - 50) / 50; -// maxInt = (maxInt - 50) / 50; -// return new SimplexMask(scale, minInt, maxInt); -// } -// // @Command( // name = "#light", // desc = "Restrict to specific light levels" @@ -133,40 +121,7 @@ // public Mask nolight(Extent extent) { // return new LightMask(extent, 0, 0); // } -// -// @Command( -// name = "#region", -// aliases = {"#selection", "#sel"}, -// desc = "inside the provided selection" -// ) -// public Mask selection(Player player, LocalSession session) throws IncompleteRegionException { -// return new RegionMask(session.getSelection(player.getWorld()).clone()); -// } -// -// @Command( -// name = "#xaxis", -// desc = "Restrict to initial x axis" -// ) -// public Mask xaxis() { -// return new XAxisMask(); -// } -// -// @Command( -// name = "#yaxis", -// desc = "Restrict to initial y axis" -// ) -// public Mask yaxis() { -// return new YAxisMask(); -// } -// -// @Command( -// name = "#zaxis", -// desc = "Restrict to initial z axis" -// ) -// public Mask zaxis() { -// return new ZAxisMask(); -// } -// + // @Command( // name = "#iddata", // desc = "Restrict to initial block id and data" @@ -174,132 +129,4 @@ // public Mask iddata(Extent extent) { // return new IdDataMask(extent); // } -// -// @Command( -// name = "#wall", -// desc = "Restrict to walls (any block n,e,s,w of air)" -// ) -// public Mask wall(Extent extent) { -// Mask blockMask = air(extent); -// return new MaskUnion(new ExistingBlockMask(extent), new WallMask(blockMask, 1, 8)); -// } -// -// @Command( -// name = "#surface", -// desc = "Restrict to surfaces (any solid block touching air)" -// ) -// public Mask surface(Extent extent) { -// return new SurfaceMask(extent); -// } -// -// @Command( -// name = "\\", -// aliases = {"/", "#angle", "#\\", "#/"}, -// desc = "Restrict to specific terrain angle", -// descFooter = "Restrict to specific terrain angle\n" + -// "The -o flag will only overlay\n" + -// "Example: /[0d][45d]\n" + -// "Explanation: Allows any block where the adjacent block is between 0 and 45 degrees.\n" + -// "Example: /[3][20]\n" + -// "Explanation: Allows any block where the adjacent block is between 3 and 20 blocks below" -//) -// public Mask angle(Extent extent, @Arg(name="min", desc = "min angle") String minStr, @Arg(name="max", desc = "max angle") String maxStr, @Switch(name = 'o', desc = "TODO") boolean overlay, @Arg(name = "distance", desc = "int", def = "1") int distanceOpt) throws ExpressionException { -// double y1, y2; -// boolean override; -// if (maxStr.endsWith("d")) { -// double y1d = Expression.compile(minStr.substring(0, minStr.length() - 1)).evaluate(); -// double y2d = Expression.compile(maxStr.substring(0, maxStr.length() - 1)).evaluate(); -// y1 = Math.tan(y1d * (Math.PI / 180)); -// y2 = Math.tan(y2d * (Math.PI / 180)); -// } else { -// y1 = Expression.compile(minStr).evaluate(); -// y2 = Expression.compile(maxStr).evaluate(); -// } -// return new AngleMask(extent, y1, y2, overlay, distanceOpt); -// } -// -// @Command( -// name = "(", -// aliases = {")", "#roc", "#(", "#)"}, -// desc = "Restrict to near specific terrain slope rate of change", -// descFooter = "Restrict to near specific terrain slope rate of change\n" + -// "The -o flag will only overlay\n" + -// "Example: ([0d][45d][5]\n" + -// "Explanation: Restrict near where the angle changes between 0-45 degrees within 5 blocks\n" + -// "Note: Use negatives for decreasing slope" -//) -// public Mask roc(Extent extent, @Arg(name="min", desc = "min angle") String minStr, @Arg(name="max", desc = "max angle") String maxStr, @Switch(name = 'o', desc = "TODO") boolean overlay, @Arg(name = "distance", desc = "int", def = "4") int distanceOpt) throws ExpressionException { -// double y1, y2; -// boolean override; -// if (maxStr.endsWith("d")) { -// double y1d = Expression.compile(minStr.substring(0, minStr.length() - 1)).evaluate(); -// double y2d = Expression.compile(maxStr.substring(0, maxStr.length() - 1)).evaluate(); -// y1 = Math.tan(y1d * (Math.PI / 180)); -// y2 = Math.tan(y2d * (Math.PI / 180)); -// } else { -// y1 = Expression.compile(minStr).evaluate(); -// y2 = Expression.compile(maxStr).evaluate(); -// } -// return new ROCAngleMask(extent, y1, y2, overlay, distanceOpt); -// } -// -// @Command( -// name = "^", -// aliases = {"#extrema", "#^"}, -// desc = "Restrict to near specific terrain extrema", -// descFooter = "Restrict to near specific terrain extrema\n" + -// "The -o flag will only overlay\n" + -// "Example: ([0d][45d][5]\n" + -// "Explanation: Restrict to near 45 degrees of local maxima\n" + -// "Note: Use negatives for local minima" -//) -// public Mask extrema(Extent extent, @Arg(name="min", desc = "min angle") String minStr, @Arg(name="max", desc = "max angle") String maxStr, @Switch(name = 'o', desc = "TODO") boolean overlay, @Arg(name = "distance", desc = "int", def = "4") int distanceOpt) throws ExpressionException { -// double y1, y2; -// boolean override; -// if (maxStr.endsWith("d")) { -// double y1d = Expression.compile(minStr.substring(0, minStr.length() - 1)).evaluate(); -// double y2d = Expression.compile(maxStr.substring(0, maxStr.length() - 1)).evaluate(); -// y1 = Math.tan(y1d * (Math.PI / 180)); -// y2 = Math.tan(y2d * (Math.PI / 180)); -// } else { -// y1 = Expression.compile(minStr).evaluate(); -// y2 = Expression.compile(maxStr).evaluate(); -// } -// return new ExtremaMask(extent, y1, y2, overlay, distanceOpt); -// } -// -// @Command( -// name = "{", -// aliases = {"#{"}, -// desc = "Restricts blocks to within a specific radius range of the initial block" -//) -// public Mask radius(@Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) throws ExpressionException { -// return new RadiusMask((int) minInt, (int) maxInt); -// } -// -// @Command( -// name = "|", -// aliases = {"#|", "#side"}, -// desc = "sides with a specific number of other blocks" -//) -// public Mask wall(@Arg(desc = "Mask") Mask mask, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) throws ExpressionException { -// return new WallMask(mask, (int) minInt, (int) maxInt); -// } -// -// @Command( -// name = "~", -// aliases = {"#~", "#adjacent"}, -// desc = "Adjacent to a specific number of other blocks" -//) -// public Mask adjacent(@Arg(desc = "Mask") Mask mask, @Arg(name = "min", desc = "double", def = "-1") double min, @Arg(name = "max", desc = "double", def = "-1") double max) throws ExpressionException { -// if (min == -1 && max == -1) { -// min = 1; -// max = 8; -// } else if (max == -1) max = min; -// if (max >= 8 && min == 1) { -// return new AdjacentAnyMask(mask); -// } -// return new AdjacentMask(mask, (int) min, (int) max); -// } -// //} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java index 405375355..211817d9e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java @@ -20,27 +20,7 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.extension.factory.parser.mask.AirMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.AngleMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.BiomeMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.BlockCategoryMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.BlockStateMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.BlocksMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.ExistingMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.ExpressionMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.FalseMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.LiquidMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.NegateMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.NoiseMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.OffsetMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.RegionMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.SimplexMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.SolidMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.TrueMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.XAxisMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.YAxisMaskParser; -import com.sk89q.worldedit.extension.factory.parser.mask.ZAxisMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.*; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.NoMatchException; import com.sk89q.worldedit.extension.input.ParserContext; @@ -82,15 +62,21 @@ public final class MaskFactory extends AbstractFactory { register(new BlockCategoryMaskParser(worldEdit)); register(new BiomeMaskParser(worldEdit)); // Mask Parsers from FAWE - register(new FalseMaskParser(worldEdit)); - register(new TrueMaskParser(worldEdit)); + register(new AdjacentMaskParser(worldEdit)); register(new AirMaskParser(worldEdit)); + register(new AngleMaskParser(worldEdit)); + register(new ExtremaMaskParser(worldEdit)); + register(new FalseMaskParser(worldEdit)); register(new LiquidMaskParser(worldEdit)); + //register(new RadiusMaskParser(worldEdit)); TODO: Adapt to work with FAWE's Chunk I/O + register(new ROCAngleMaskParser(worldEdit)); + register(new SimplexMaskParser(worldEdit)); + register(new SurfaceMaskParser(worldEdit)); + register(new TrueMaskParser(worldEdit)); + register(new WallMaskParser(worldEdit)); register(new XAxisMaskParser(worldEdit)); register(new YAxisMaskParser(worldEdit)); register(new ZAxisMaskParser(worldEdit)); - register(new SimplexMaskParser(worldEdit)); - register(new AngleMaskParser(worldEdit)); } 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 new file mode 100644 index 000000000..0dd9f768c --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/AdjacentMaskParser.java @@ -0,0 +1,45 @@ +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.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 org.jetbrains.annotations.NotNull; + +import java.util.stream.Stream; + +public class AdjacentMaskParser extends RichParser { + + public AdjacentMaskParser(WorldEdit worldEdit) { + super(worldEdit,"~"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + if(index == 0){ + return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + } else if (index == 1 || index == 2) { + return this.suggestPositiveDoubles(argumentInput); + } + return Stream.empty(); + } + + @Override + protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if(arguments.length == 0) return null; + Mask subMask = worldEdit.getMaskFactory().parseFromInput(arguments[0], context); + int min = arguments.length > 1 ? Integer.parseInt(arguments[1]) : -1; + int max = arguments.length > 2 ? Integer.parseInt(arguments[2]) : -1; + if (min == -1 && max == -1) { + min = 1; + max = 8; + } else if (max == -1) max = min; + if (max >= 8 && min == 1) { + return new AdjacentAnyMask(subMask); + } + return new AdjacentMask(subMask, (int) min, (int) max); + } +} 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 0957a7e8c..a3b3982ea 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 @@ -12,6 +12,8 @@ import java.util.stream.Stream; public class AngleMaskParser extends RichParser { + private final String[] flags = new String[]{"-o"}; + public AngleMaskParser(WorldEdit worldEdit) { super(worldEdit, "/"); } @@ -20,13 +22,15 @@ public class AngleMaskParser extends RichParser { protected Stream getSuggestions(String argumentInput, int index) { if (index == 0 || index == 1) { return suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); + } else if (index > 1 && index <= 1 + flags.length) { + return Stream.of(flags); } - return null; + return Stream.empty(); } @Override protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { - if (arguments.length != 2) return null; + if (arguments.length < 2 || arguments.length > 2 + flags.length) return null; String minArg = arguments[0]; String maxArg = arguments[1]; boolean degree = minArg.endsWith("d"); @@ -34,6 +38,17 @@ public class AngleMaskParser extends RichParser { throw new InputParseException("Cannot combine degree with block-step"); } double min, max; + boolean overlay = false; + if (arguments.length > 2) { + for (int index = 2; index < 2 + flags.length; index++) { + String flag = arguments[index]; + if (flag.equals("-o")) { + overlay = true; + } else { + throw new InputParseException("The flag " + flag + " is not applicable for this mask!"); + } + } + } if (degree) { double minDeg = Double.parseDouble(minArg.substring(0, minArg.length() - 1)); double maxDeg = Double.parseDouble(maxArg.substring(0, maxArg.length() - 1)); @@ -44,6 +59,6 @@ public class AngleMaskParser extends RichParser { max = Double.parseDouble(maxArg); } - return new AngleMask(context.getExtent(), min, max, false, 1); + return new AngleMask(context.getExtent(), min, max, overlay, 1); } } 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 new file mode 100644 index 000000000..c6227a9c1 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExtremaMaskParser.java @@ -0,0 +1,64 @@ +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.boydti.fawe.object.mask.ExtremaMask; +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.mask.Mask; +import org.jetbrains.annotations.NotNull; + +import java.util.stream.Stream; + +public class ExtremaMaskParser extends RichParser { + + private final String[] flags = new String[]{"-o"}; + + public ExtremaMaskParser(WorldEdit worldEdit) { + super(worldEdit, "#extrema"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + if (index == 0 || index == 1) { + return suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); + } else if (index > 1 && index <= 1 + flags.length) { + return Stream.of(flags); + } + return Stream.empty(); + } + + @Override + protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if (arguments.length < 2 || arguments.length > 2 + flags.length) return null; + String minArg = arguments[0]; + String maxArg = arguments[1]; + boolean degree = minArg.endsWith("d"); + if (degree ^ maxArg.endsWith("d")) { + throw new InputParseException("Cannot combine degree with block-step"); + } + double min, max; + boolean overlay = false; + if (arguments.length > 2) { + for (int index = 2; index < 2 + flags.length; index++) { + String flag = arguments[index]; + if (flag.equals("-o")) { + overlay = true; + } else { + throw new InputParseException("The flag " + flag + " is not applicable for this mask!"); + } + } + } + if (degree) { + double minDeg = Double.parseDouble(minArg.substring(0, minArg.length() - 1)); + double maxDeg = Double.parseDouble(maxArg.substring(0, maxArg.length() - 1)); + min = (Math.tan(minDeg * (Math.PI / 180))); + max = (Math.tan(maxDeg * (Math.PI / 180))); + } else { + min = Double.parseDouble(minArg); + max = Double.parseDouble(maxArg); + } + + return new ExtremaMask(context.getExtent(), min, max, overlay, 4); + } +} 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 new file mode 100644 index 000000000..4dee4289e --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ROCAngleMaskParser.java @@ -0,0 +1,64 @@ +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.boydti.fawe.object.mask.ROCAngleMask; +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.mask.Mask; +import org.jetbrains.annotations.NotNull; + +import java.util.stream.Stream; + +public class ROCAngleMaskParser extends RichParser { + + private final String[] flags = new String[]{"-o"}; + + public ROCAngleMaskParser(WorldEdit worldEdit) { + super(worldEdit, "#roc"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + if (index == 0 || index == 1) { + return suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); + } else if (index > 1 && index <= 1 + flags.length) { + return Stream.of(flags); + } + return Stream.empty(); + } + + @Override + protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if (arguments.length < 2 || arguments.length > 2 + flags.length) return null; + String minArg = arguments[0]; + String maxArg = arguments[1]; + boolean degree = minArg.endsWith("d"); + if (degree ^ maxArg.endsWith("d")) { + throw new InputParseException("Cannot combine degree with block-step"); + } + double min, max; + boolean overlay = false; + if (arguments.length > 2) { + for (int index = 2; index < 2 + flags.length; index++) { + String flag = arguments[index]; + if (flag.equals("-o")) { + overlay = true; + } else { + throw new InputParseException("The flag " + flag + " is not applicable for this mask!"); + } + } + } + if (degree) { + double minDeg = Double.parseDouble(minArg.substring(0, minArg.length() - 1)); + double maxDeg = Double.parseDouble(maxArg.substring(0, maxArg.length() - 1)); + min = (Math.tan(minDeg * (Math.PI / 180))); + max = (Math.tan(maxDeg * (Math.PI / 180))); + } else { + min = Double.parseDouble(minArg); + max = Double.parseDouble(maxArg); + } + + return new ROCAngleMask(context.getExtent(), min, max, overlay, 4); + } +} 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 new file mode 100644 index 000000000..9caa169e9 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RadiusMaskParser.java @@ -0,0 +1,35 @@ +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.boydti.fawe.object.mask.RadiusMask; +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.mask.Mask; +import org.jetbrains.annotations.NotNull; + +import java.util.stream.Stream; + +public class RadiusMaskParser extends RichParser { + + public RadiusMaskParser(WorldEdit worldEdit) { + super(worldEdit, "{"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + if(index == 0 || index == 1){ + return suggestPositiveDoubles(argumentInput); + } + return Stream.empty(); + } + + @Override + protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if(arguments.length < 2) return null; + int min = Integer.parseInt(arguments[0]); + int max = Integer.parseInt(arguments[1]); + System.out.println("radius: " + min + " | " + max); + return new RadiusMask(min, max); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SurfaceMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SurfaceMaskParser.java new file mode 100644 index 000000000..e485afb04 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SurfaceMaskParser.java @@ -0,0 +1,30 @@ +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.boydti.fawe.object.mask.SurfaceMask; +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.WorldEdit; +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.internal.registry.SimpleInputParser; + +import java.util.List; + +public class SurfaceMaskParser extends SimpleInputParser { + + private final List aliases = ImmutableList.of("#surface"); + + public SurfaceMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return aliases; + } + + @Override + public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + return new SurfaceMask(context.getExtent()); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/WallMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/WallMaskParser.java new file mode 100644 index 000000000..d1b7c0f7b --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/WallMaskParser.java @@ -0,0 +1,31 @@ +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.boydti.fawe.object.mask.WallMask; +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.*; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; +import com.sk89q.worldedit.world.block.BlockTypes; + +import java.util.List; + +public class WallMaskParser extends SimpleInputParser { + + private final List aliases = ImmutableList.of("#wall"); + + public WallMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return aliases; + } + + @Override + public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + return new MaskIntersection(new ExistingBlockMask(context.getExtent()), new WallMask(new BlockMask(context.getExtent(), BlockTypes.AIR.getDefaultState().toBaseBlock()), 1, 8)); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index 952ec9b5d..dc9dbb664 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -321,6 +321,11 @@ public class BlockMask extends ABlockMask { for (int i = 0; i < cloned.length; i++) { cloned[i] = !cloned[i]; } + if(replacesAir()){ + cloned[BlockTypes.AIR.getDefaultState().getOrdinal()] = false; + cloned[BlockTypes.CAVE_AIR.getDefaultState().getOrdinal()] = false; + cloned[BlockTypes.VOID_AIR.getDefaultState().getOrdinal()] = false; + } return new BlockMask(getExtent(), cloned); } } From dc465f7d3c3bbb0e75197b0226a44c11221bb83a Mon Sep 17 00:00:00 2001 From: IronApollo Date: Mon, 7 Sep 2020 21:46:54 -0400 Subject: [PATCH 2/2] Reformat, fix RichParser suggestions --- .../boydti/fawe/object/mask/AngleMask.java | 28 +++++++++---------- .../boydti/fawe/object/mask/ROCAngleMask.java | 10 +++---- .../boydti/fawe/object/mask/SurfaceMask.java | 6 ++-- .../extension/factory/MaskFactory.java | 27 +++++++++++++++++- .../extension/factory/parser/RichParser.java | 8 +++--- .../parser/mask/AdjacentMaskParser.java | 8 +++--- .../factory/parser/mask/RadiusMaskParser.java | 5 ++-- 7 files changed, 58 insertions(+), 34 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java index f5f48d698..4d5fba6bb 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java @@ -94,32 +94,32 @@ public class AngleMask extends SolidBlockMask implements ResettableMask { boolean aboveMin; lastY = y; slope = - Math.abs(getHeight(extent, x + distance, y, z) - getHeight(extent, x - distance, y, z)) - * ADJACENT_MOD; + Math.abs(getHeight(extent, x + distance, y, z) - getHeight(extent, x - distance, y, z)) + * ADJACENT_MOD; if (checkFirst) { if (slope >= min) { return lastValue = true; } slope = Math.max(slope, Math.abs( - getHeight(extent, x, y, z + distance) - getHeight(extent, x, y, z - distance)) - * ADJACENT_MOD); + getHeight(extent, x, y, z + distance) - getHeight(extent, x, y, z - distance)) + * ADJACENT_MOD); slope = Math.max(slope, Math.abs( - getHeight(extent, x + distance, y, z + distance) - getHeight(extent, - x - distance, y, z - distance)) * DIAGONAL_MOD); + getHeight(extent, x + distance, y, z + distance) - getHeight(extent, + x - distance, y, z - distance)) * DIAGONAL_MOD); slope = Math.max(slope, Math.abs( - getHeight(extent, x - distance, y, z + distance) - getHeight(extent, - x + distance, y, z - distance)) * DIAGONAL_MOD); + getHeight(extent, x - distance, y, z + distance) - getHeight(extent, + x + distance, y, z - distance)) * DIAGONAL_MOD); return lastValue = (slope >= min); } else { slope = Math.max(slope, Math.abs( - getHeight(extent, x, y, z + distance) - getHeight(extent, x, y, z - distance)) - * ADJACENT_MOD); + getHeight(extent, x, y, z + distance) - getHeight(extent, x, y, z - distance)) + * ADJACENT_MOD); slope = Math.max(slope, Math.abs( - getHeight(extent, x + distance, y, z + distance) - getHeight(extent, - x - distance, y, z - distance)) * DIAGONAL_MOD); + getHeight(extent, x + distance, y, z + distance) - getHeight(extent, + x - distance, y, z - distance)) * DIAGONAL_MOD); slope = Math.max(slope, Math.abs( - getHeight(extent, x - distance, y, z + distance) - getHeight(extent, - x + distance, y, z - distance)) * DIAGONAL_MOD); + getHeight(extent, x - distance, y, z + distance) - getHeight(extent, + x + distance, y, z - distance)) * DIAGONAL_MOD); return lastValue = (slope >= min && slope <= max); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/ROCAngleMask.java b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/ROCAngleMask.java index ee7f542d2..a7da74224 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/ROCAngleMask.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/ROCAngleMask.java @@ -14,19 +14,19 @@ public class ROCAngleMask extends AngleMask { int base = getHeight(extent, x, y, z); double slope = - (getHeight(extent, x + distance, y, z) - base - (base - getHeight(extent, x - distance, y, z))) - * ADJACENT_MOD; + (getHeight(extent, x + distance, y, z) - base - (base - getHeight(extent, x - distance, y, z))) + * ADJACENT_MOD; double tmp = (getHeight(extent, x, y, z + distance) - base - (base - getHeight(extent, x, y, - z - distance))) * ADJACENT_MOD; + z - distance))) * ADJACENT_MOD; if (Math.abs(tmp) > Math.abs(slope)) slope = tmp; tmp = (getHeight(extent, x + distance, y, z + distance) - base - (base - getHeight(extent, x - distance, y, - z - distance))) * DIAGONAL_MOD; + z - distance))) * DIAGONAL_MOD; if (Math.abs(tmp) > Math.abs(slope)) slope = tmp; tmp = (getHeight(extent, x - distance, y, z + distance) - base - (base - getHeight(extent, x + distance, y, - z - distance))) * DIAGONAL_MOD; + z - distance))) * DIAGONAL_MOD; if (Math.abs(tmp) > Math.abs(slope)) slope = tmp; return lastValue = slope >= min && slope <= max; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java index 3413e6878..9534be6dc 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java @@ -13,9 +13,9 @@ public class SurfaceMask extends AdjacentAnyMask { public static AbstractExtentMask getMask(Extent extent) { return new BlockMaskBuilder() - .addTypes(BlockTypes.AIR, BlockTypes.CAVE_AIR, BlockTypes.VOID_AIR) - .addAll(b -> !b.getMaterial().isMovementBlocker()) - .build(extent); + .addTypes(BlockTypes.AIR, BlockTypes.CAVE_AIR, BlockTypes.VOID_AIR) + .addAll(b -> !b.getMaterial().isMovementBlocker()) + .build(extent); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java index 211817d9e..52ce3ba43 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java @@ -20,7 +20,32 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.extension.factory.parser.mask.*; +import com.sk89q.worldedit.extension.factory.parser.mask.AdjacentMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.AirMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.AngleMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.BiomeMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.BlockCategoryMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.BlockStateMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.BlocksMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.ExistingMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.ExpressionMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.ExtremaMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.FalseMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.LiquidMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.NegateMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.NoiseMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.OffsetMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.ROCAngleMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.RegionMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.SimplexMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.SolidMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.SurfaceMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.TrueMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.WallMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.XAxisMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.YAxisMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.ZAxisMaskParser; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.NoMatchException; import com.sk89q.worldedit.extension.input.ParserContext; 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 7c19f55b0..5d625826d 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 @@ -36,7 +36,7 @@ public abstract class RichParser extends InputParser { @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)) { + 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 @@ -45,11 +45,11 @@ public abstract class RichParser extends InputParser { } // we know that it is at least "" String[] strings = extractArguments(input.substring(this.prefix.length()), false); - StringJoiner joiner = new StringJoiner(","); + StringBuilder builder = new StringBuilder(); for (int i = 0; i < strings.length - 1; i++) { - joiner.add("[" + strings[i] + "]"); + builder.append('[').append(strings[i]).append(']'); } - String previous = this.prefix + joiner; + String previous = this.prefix + builder; return getSuggestions(strings[strings.length - 1], strings.length - 1).map(s -> previous + "[" + s + "]"); } 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 0dd9f768c..128c51d9a 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 @@ -14,12 +14,12 @@ import java.util.stream.Stream; public class AdjacentMaskParser extends RichParser { public AdjacentMaskParser(WorldEdit worldEdit) { - super(worldEdit,"~"); + super(worldEdit, "~"); } @Override protected Stream getSuggestions(String argumentInput, int index) { - if(index == 0){ + if (index == 0) { return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); } else if (index == 1 || index == 2) { return this.suggestPositiveDoubles(argumentInput); @@ -29,7 +29,7 @@ public class AdjacentMaskParser extends RichParser { @Override protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { - if(arguments.length == 0) return null; + if (arguments.length == 0) return null; Mask subMask = worldEdit.getMaskFactory().parseFromInput(arguments[0], context); int min = arguments.length > 1 ? Integer.parseInt(arguments[1]) : -1; int max = arguments.length > 2 ? Integer.parseInt(arguments[2]) : -1; @@ -40,6 +40,6 @@ public class AdjacentMaskParser extends RichParser { if (max >= 8 && min == 1) { return new AdjacentAnyMask(subMask); } - return new AdjacentMask(subMask, (int) min, (int) max); + return new AdjacentMask(subMask, min, max); } } 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 9caa169e9..bfc78863a 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 @@ -18,7 +18,7 @@ public class RadiusMaskParser extends RichParser { @Override protected Stream getSuggestions(String argumentInput, int index) { - if(index == 0 || index == 1){ + if (index == 0 || index == 1) { return suggestPositiveDoubles(argumentInput); } return Stream.empty(); @@ -26,10 +26,9 @@ public class RadiusMaskParser extends RichParser { @Override protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { - if(arguments.length < 2) return null; + if (arguments.length < 2) return null; int min = Integer.parseInt(arguments[0]); int max = Integer.parseInt(arguments[1]); - System.out.println("radius: " + min + " | " + max); return new RadiusMask(min, max); } }