From 9e6b3fabe4f05162cafbddda2d990aa7eff3aae4 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Wed, 22 Aug 2018 03:10:20 +1000 Subject: [PATCH] Use expression for brush radius --- .../fawe/command/FawePrimitiveBinding.java | 22 +++ .../fawe/object/brush/BrushSettings.java | 38 ++++- .../fawe/object/brush/CommandBrush.java | 2 +- .../worldedit/command/BrushCommands.java | 132 ++++++++++-------- .../command/BrushOptionsCommands.java | 6 +- .../worldedit/command/tool/BrushTool.java | 25 ++-- .../internal/expression/Expression.java | 12 ++ 7 files changed, 157 insertions(+), 80 deletions(-) diff --git a/core/src/main/java/com/boydti/fawe/command/FawePrimitiveBinding.java b/core/src/main/java/com/boydti/fawe/command/FawePrimitiveBinding.java index b049c029..ad350212 100644 --- a/core/src/main/java/com/boydti/fawe/command/FawePrimitiveBinding.java +++ b/core/src/main/java/com/boydti/fawe/command/FawePrimitiveBinding.java @@ -176,6 +176,28 @@ public class FawePrimitiveBinding extends BindingHelper { return v; } + @BindingMatch(type = { Expression.class }, + behavior = BindingBehavior.CONSUMES, + consumedCount = 1) + public Expression getExpression(ArgumentStack context) throws ParameterException, ExpressionException { + String input = context.next(); + try { + return new Expression(Double.parseDouble(input)); + } catch (NumberFormatException e1) { + try { + Expression expression = Expression.compile(input); + expression.optimize(); + return expression; + } catch (EvaluationException e) { + throw new ParameterException(String.format( + "Expected '%s' to be a valid number (or a valid mathematical expression)", input)); + } catch (ExpressionException e) { + throw new ParameterException(String.format( + "Expected '%s' to be a number or valid math expression (error: %s)", input, e.getMessage())); + } + } + } + /** * Gets a type from a {@link ArgumentStack}. * diff --git a/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java b/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java index 96454f8c..0dde4592 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java @@ -16,6 +16,10 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.expression.Expression; +import com.sk89q.worldedit.internal.expression.ExpressionException; +import com.sk89q.worldedit.internal.expression.runtime.Constant; +import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.ProcessedCallable; @@ -26,6 +30,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import static com.google.common.base.Preconditions.checkNotNull; + public class BrushSettings { public enum SettingType { BRUSH, @@ -45,7 +51,7 @@ public class BrushSettings { private Mask sourceMask = null; private ResettableExtent transform = null; private Pattern material; - private double size = 1; + private Expression size = new Expression(1); private Set permissions; private ScrollAction scrollAction; private String lastWorld; @@ -78,7 +84,12 @@ public class BrushSettings { bs.permissions.addAll((Collection) settings.get(SettingType.PERMISSIONS.name())); } if (settings.containsKey(SettingType.SIZE.name())) { - bs.size = (double) settings.get(SettingType.SIZE.name()); + try { + bs.size = Expression.compile((String) settings.getOrDefault(SettingType.SIZE.name(), -1)); + bs.size.optimize(); + } catch (ExpressionException e) { + throw new RuntimeException(e); + } } ParserContext parserContext = new ParserContext(); @@ -140,7 +151,7 @@ public class BrushSettings { transform = null; material = null; scrollAction = null; - size = 1; + size = new Expression(1); permissions.clear(); constructor.clear(); return this; @@ -184,16 +195,21 @@ public class BrushSettings { return this; } - public BrushSettings setSize(double size) { + public BrushSettings setSize(Expression size) { + checkNotNull(size); this.size = size; - if (size == -1) { + if (size.getRoot() instanceof Constant && ((Constant) size.getRoot()).getValue() == -1) { constructor.remove(SettingType.SIZE); } else { - constructor.put(SettingType.SIZE, size); + constructor.put(SettingType.SIZE, size.toString()); } return this; } + public BrushSettings setSize(double size) { + return setSize(new Expression(size)); + } + public BrushSettings setScrollAction(ScrollAction scrollAction) { if (scrollAction == null) constructor.remove(SettingType.SCROLL_ACTION); this.scrollAction = scrollAction; @@ -245,7 +261,15 @@ public class BrushSettings { } public double getSize() { - return size; + try { + return size.evaluate(); + } catch (EvaluationException e) { + throw new RuntimeException(e); + } + } + + public Expression getSizeExpression() { + return this.size; } public Set getPermissions() { diff --git a/core/src/main/java/com/boydti/fawe/object/brush/CommandBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/CommandBrush.java index b2ebb36b..1e3cd0fe 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/CommandBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/CommandBrush.java @@ -22,7 +22,7 @@ public class CommandBrush implements Brush { private final String command; - public CommandBrush(String command, double radius) { + public CommandBrush(String command) { this.command = command.charAt(0) == '/' ? "/" + command : command; } diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 5a829d0f..513bc966 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -50,6 +50,9 @@ import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.expression.Expression; +import com.sk89q.worldedit.internal.expression.runtime.Constant; +import com.sk89q.worldedit.internal.expression.runtime.RValue; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.command.InvalidUsageException; import com.sk89q.worldedit.util.command.binding.Range; @@ -76,6 +79,15 @@ public class BrushCommands extends BrushProcessor { super(worldEdit); } + public static void checkMaxBrushRadius(Expression radius) throws MaxBrushRadiusException { + if (WorldEdit.getInstance().getConfiguration().maxBrushRadius > 0) { + RValue r = radius.getRoot(); + if (r instanceof Constant && ((Constant) r).getValue() > WorldEdit.getInstance().getConfiguration().maxBrushRadius) { + throw new MaxBrushRadiusException(); + } + } + } + @Command( aliases = {"blendball", "bb", "blend"}, usage = "[radius=5]", @@ -86,8 +98,8 @@ public class BrushCommands extends BrushProcessor { max = 1 ) @CommandPermissions("worldedit.brush.blendball") - public BrushSettings blendBallBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings blendBallBrush(Player player, LocalSession session, @Optional("5") Expression radius, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new BlendBall()).setSize(radius); } @@ -100,8 +112,8 @@ public class BrushCommands extends BrushProcessor { max = 1 ) @CommandPermissions("worldedit.brush.erode") - public BrushSettings erodeBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings erodeBrush(Player player, LocalSession session, @Optional("5") Expression radius, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new ErodeBrush()).setSize(radius); } @@ -114,8 +126,8 @@ public class BrushCommands extends BrushProcessor { max = 1 ) @CommandPermissions("worldedit.brush.pull") - public BrushSettings pullBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings pullBrush(Player player, LocalSession session, @Optional("5") Expression radius, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new RaiseBrush()).setSize(radius); } @@ -129,8 +141,8 @@ public class BrushCommands extends BrushProcessor { max = 2 ) @CommandPermissions("worldedit.brush.sphere") - public BrushSettings circleBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings circleBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") Expression radius, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new CircleBrush(player)).setSize(radius).setFill(fill); } @@ -145,8 +157,8 @@ public class BrushCommands extends BrushProcessor { max = 3 ) @CommandPermissions("worldedit.brush.recursive") - public BrushSettings recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("5") double radius, @Switch('d') boolean depthFirst, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("5") Expression radius, @Switch('d') boolean depthFirst, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new RecurseBrush(depthFirst)) .setSize(radius) @@ -168,8 +180,8 @@ public class BrushCommands extends BrushProcessor { max = 2 ) @CommandPermissions("worldedit.brush.line") - public BrushSettings lineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings lineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") Expression radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new LineBrush(shell, select, flat)) .setSize(radius) @@ -189,8 +201,8 @@ public class BrushCommands extends BrushProcessor { max = 2 ) @CommandPermissions("worldedit.brush.spline") - public BrushSettings splineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("25") double radius, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings splineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("25") Expression radius, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius)); return set(session, context, new SplineBrush(player, session)) @@ -227,8 +239,8 @@ public class BrushCommands extends BrushProcessor { max = 3 ) @CommandPermissions("worldedit.brush.spline") - public BrushSettings catenaryBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("1.2") @Range(min=1) double lengthFactor, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('d') boolean facingDirection, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings catenaryBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("1.2") @Range(min=1) double lengthFactor, @Optional("0") Expression radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('d') boolean facingDirection, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new CatenaryBrush(shell, select, facingDirection, lengthFactor)) .setSize(radius) @@ -245,9 +257,9 @@ public class BrushCommands extends BrushProcessor { max = 6 ) @CommandPermissions("worldedit.brush.surfacespline") // 0, 0, 0, 10, 0, - public BrushSettings surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality, CommandContext context) throws WorldEditException { + public BrushSettings surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") Expression radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality, CommandContext context) throws WorldEditException { player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius)); - getWorldEdit().checkMaxBrushRadius(radius); + checkMaxBrushRadius(radius); return set(session, context, new SurfaceSpline(tension, bias, continuity, quality)) .setSize(radius) @@ -265,7 +277,7 @@ public class BrushCommands extends BrushProcessor { @CommandPermissions("worldedit.brush.rock") public BrushSettings blobBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") Vector radius, @Optional("100") double sphericity, @Optional("30") double frequency, @Optional("50") double amplitude, CommandContext context) throws WorldEditException { double max = MathMan.max(radius.getBlockX(), radius.getBlockY(), radius.getBlockZ()); - getWorldEdit().checkMaxBrushRadius(max); + WorldEdit.getInstance().checkMaxBrushRadius(max); Brush brush = new BlobBrush(radius.divide(max), frequency / 100, amplitude / 100, sphericity / 100); return set(session, context, brush) @@ -286,8 +298,8 @@ public class BrushCommands extends BrushProcessor { max = 2 ) @CommandPermissions("worldedit.brush.sphere") - public BrushSettings sphereBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("2") @Range(min=0) double radius, @Switch('h') boolean hollow, @Switch('f') boolean falling, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings sphereBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("2") @Range(min=0) Expression radius, @Switch('h') boolean hollow, @Switch('f') boolean falling, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); Brush brush; if (hollow) { @@ -327,8 +339,8 @@ public class BrushCommands extends BrushProcessor { max = -1 ) @CommandPermissions("worldedit.brush.shatter") - public BrushSettings shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") Expression radius, @Optional("10") int count, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new ShatterBrush(count)) .setSize(radius) @@ -348,8 +360,8 @@ public class BrushCommands extends BrushProcessor { max = -1 ) @CommandPermissions("worldedit.brush.stencil") - public BrushSettings stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") Expression radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); InputStream stream = getHeightmapStream(image); HeightBrush brush; try { @@ -379,8 +391,8 @@ public class BrushCommands extends BrushProcessor { max = -1 ) @CommandPermissions("worldedit.brush.stencil") - public BrushSettings imageBrush(Player player, EditSession editSession, LocalSession session, @Optional("5") double radius, BufferedImage image, @Optional("1") @Range(min=Double.MIN_NORMAL) final double yscale, @Switch('a') boolean alpha, @Switch('f') boolean fadeOut, CommandContext context) throws WorldEditException, IOException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings imageBrush(Player player, EditSession editSession, LocalSession session, @Optional("5") Expression radius, BufferedImage image, @Optional("1") @Range(min=Double.MIN_NORMAL) final double yscale, @Switch('a') boolean alpha, @Switch('f') boolean fadeOut, CommandContext context) throws WorldEditException, IOException { + checkMaxBrushRadius(radius); if (yscale != 1) { ImageUtil.scaleAlpha(image, yscale); alpha = true; @@ -407,8 +419,8 @@ public class BrushCommands extends BrushProcessor { max = -1 ) @CommandPermissions("worldedit.brush.surface") - public BrushSettings surfaceBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings surfaceBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") Expression radius, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new SurfaceSphereBrush()).setFill(fill).setSize(radius); } @@ -425,8 +437,8 @@ public class BrushCommands extends BrushProcessor { max = 4 ) @CommandPermissions("worldedit.brush.scatter") - public BrushSettings scatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("5") double points, @Optional("1") double distance, @Switch('o') boolean overlay, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings scatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") Expression radius, @Optional("5") double points, @Optional("1") double distance, @Switch('o') boolean overlay, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); Brush brush; if (overlay) { brush = new ScatterOverlayBrush((int) points, (int) distance); @@ -451,8 +463,8 @@ public class BrushCommands extends BrushProcessor { max = 4 ) @CommandPermissions("worldedit.brush.populateschematic") - public BrushSettings scatterSchemBrush(Player player, EditSession editSession, LocalSession session, Mask mask, String clipboard, @Optional("30") double radius, @Optional("50") double density, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings scatterSchemBrush(Player player, EditSession editSession, LocalSession session, Mask mask, String clipboard, @Optional("30") Expression radius, @Optional("50") double density, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); try { @@ -486,8 +498,8 @@ public class BrushCommands extends BrushProcessor { max = 999 ) @CommandPermissions("worldedit.brush.layer") - public BrushSettings surfaceLayer(Player player, EditSession editSession, LocalSession session, double radius, CommandContext args, CommandContext context) throws WorldEditException, InvalidUsageException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings surfaceLayer(Player player, EditSession editSession, LocalSession session, Expression radius, CommandContext args, CommandContext context) throws WorldEditException, InvalidUsageException { + checkMaxBrushRadius(radius); ParserContext parserContext = new ParserContext(); parserContext.setActor(player); parserContext.setWorld(player.getWorld()); @@ -526,8 +538,8 @@ public class BrushCommands extends BrushProcessor { max = 5 ) @CommandPermissions("worldedit.brush.splatter") - public BrushSettings splatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("1") double points, @Optional("5") double recursion, @Optional("true") boolean solid, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings splatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") Expression radius, @Optional("1") double points, @Optional("5") double recursion, @Optional("true") boolean solid, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new SplatterBrush((int) points, (int) recursion, solid)) .setSize(radius) @@ -547,8 +559,8 @@ public class BrushCommands extends BrushProcessor { max = -1 ) @CommandPermissions("worldedit.brush.scattercommand") - public BrushSettings scatterCommandBrush(Player player, EditSession editSession, LocalSession session, double radius, double points, double distance, CommandContext args, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings scatterCommandBrush(Player player, EditSession editSession, LocalSession session, Expression radius, double points, double distance, CommandContext args, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new ScatterCommand((int) points, (int) distance, args.getJoinedStrings(3))) .setSize(radius); @@ -567,9 +579,9 @@ public class BrushCommands extends BrushProcessor { ) @CommandPermissions("worldedit.brush.cylinder") public BrushSettings cylinderBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, - @Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); - getWorldEdit().checkMaxBrushRadius(height); + @Optional("2") Expression radius, @Optional("1") int height, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); + WorldEdit.getInstance().checkMaxBrushRadius(height); BrushSettings settings; if (hollow) { @@ -600,9 +612,9 @@ public class BrushCommands extends BrushProcessor { Vector size = clipboard.getDimensions(); - getWorldEdit().checkMaxBrushRadius(size.getBlockX()); - getWorldEdit().checkMaxBrushRadius(size.getBlockY()); - getWorldEdit().checkMaxBrushRadius(size.getBlockZ()); + WorldEdit.getInstance().checkMaxBrushRadius(size.getBlockX()); + WorldEdit.getInstance().checkMaxBrushRadius(size.getBlockY()); + WorldEdit.getInstance().checkMaxBrushRadius(size.getBlockZ()); return set(session, context, new ClipboardBrush(holder, ignoreAir, usingOrigin)); } @@ -619,10 +631,10 @@ public class BrushCommands extends BrushProcessor { ) @CommandPermissions("worldedit.brush.smooth") public BrushSettings smoothBrush(Player player, LocalSession session, EditSession editSession, - @Optional("2") double radius, @Optional("4") int iterations, @Switch('n') + @Optional("2") Expression radius, @Optional("4") int iterations, @Switch('n') boolean naturalBlocksOnly, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + checkMaxBrushRadius(radius); FawePlayer fp = FawePlayer.wrap(player); FaweLimit limit = Settings.IMP.getLimit(fp); @@ -641,8 +653,8 @@ public class BrushCommands extends BrushProcessor { max = 1 ) @CommandPermissions("worldedit.brush.ex") - public BrushSettings extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") Expression radius, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); Pattern fill = (new BaseBlock(0)); return set(session, context, @@ -665,8 +677,8 @@ public class BrushCommands extends BrushProcessor { max = 1 ) @CommandPermissions("worldedit.brush.gravity") - public BrushSettings gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings gravityBrush(Player player, LocalSession session, @Optional("5") Expression radius, @Switch('h') boolean fromMaxY, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); return set(session, context, new GravityBrush(fromMaxY)) @@ -689,7 +701,7 @@ public class BrushCommands extends BrushProcessor { max = 4 ) @CommandPermissions("worldedit.brush.height") - public BrushSettings heightBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { + public BrushSettings heightBrush(Player player, LocalSession session, @Optional("5") Expression radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { return terrainBrush(player, session, radius, image, rotation, yscale, false, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context); } @@ -707,7 +719,7 @@ public class BrushCommands extends BrushProcessor { max = 4 ) @CommandPermissions("worldedit.brush.height") - public BrushSettings cliffBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { + public BrushSettings cliffBrush(Player player, LocalSession session, @Optional("5") Expression radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { return terrainBrush(player, session, radius, image, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CYLINDER, context); } @@ -724,12 +736,12 @@ public class BrushCommands extends BrushProcessor { max = 4 ) @CommandPermissions("worldedit.brush.height") - public BrushSettings flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { + public BrushSettings flattenBrush(Player player, LocalSession session, @Optional("5") Expression radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { return terrainBrush(player, session, radius, image, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context); } - private BrushSettings terrainBrush(Player player, LocalSession session, double radius, String image, int rotation, double yscale, boolean flat, boolean randomRotate, boolean layers, boolean smooth, ScalableHeightMap.Shape shape, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + private BrushSettings terrainBrush(Player player, LocalSession session, Expression radius, String image, int rotation, double yscale, boolean flat, boolean randomRotate, boolean layers, boolean smooth, ScalableHeightMap.Shape shape, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); InputStream stream = getHeightmapStream(image); HeightBrush brush; if (flat) { @@ -799,8 +811,8 @@ public class BrushCommands extends BrushProcessor { max = 1 ) @CommandPermissions("worldedit.brush.copy") - public BrushSettings copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean randomRotate, @Switch('a') boolean autoRotate, CommandContext context) throws WorldEditException { - getWorldEdit().checkMaxBrushRadius(radius); + public BrushSettings copy(Player player, LocalSession session, @Optional("5") Expression radius, @Switch('r') boolean randomRotate, @Switch('a') boolean autoRotate, CommandContext context) throws WorldEditException { + checkMaxBrushRadius(radius); player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius)); return set(session, context, @@ -821,10 +833,10 @@ public class BrushCommands extends BrushProcessor { max = 99 ) @CommandPermissions("worldedit.brush.command") - public BrushSettings command(Player player, LocalSession session, double radius, CommandContext args, CommandContext context) throws WorldEditException { + public BrushSettings command(Player player, LocalSession session, Expression radius, CommandContext args, CommandContext context) throws WorldEditException { String cmd = args.getJoinedStrings(1); return set(session, context, - new CommandBrush(cmd, radius)) + new CommandBrush(cmd)) .setSize(radius); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java index 10d256ee..7635319b 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.util.command.binding.Range; import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.parametric.Optional; @@ -488,9 +489,8 @@ public class BrushOptionsCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.options.size") - public void size(Player player, LocalSession session, CommandContext args, @Switch('h') boolean offHand) throws WorldEditException { - int radius = args.getInteger(0); - worldEdit.checkMaxBrushRadius(radius); + public void size(Player player, LocalSession session, Expression radius, @Switch('h') boolean offHand) throws WorldEditException { + BrushCommands.checkMaxBrushRadius(radius); BrushTool tool = session.getBrushTool(player, false); if (tool == null) { player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f()); diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index bf0090ac..362fa2f2 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -24,14 +24,7 @@ import com.boydti.fawe.util.TaskManager; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.worldedit.BlockWorldVector; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalConfiguration; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.MutableBlockVector; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.*; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.entity.Player; @@ -43,6 +36,7 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.Location; import java.io.IOException; @@ -355,6 +349,15 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool this.getContext().setSize(radius); } + /** + * Set the set brush size. + * + * @param radius a radius + */ + public void setSize(Expression radius) { + this.getContext().setSize(radius); + } + /** * Get the set brush range. * @@ -478,11 +481,15 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool if (transform != null) { editSession.addTransform(transform); } + double size = current.getSize(); try { new PatternTraverser(current).reset(editSession); - brush.build(editSession, target, current.getMaterial(), current.getSize()); + WorldEdit.getInstance().checkMaxBrushRadius(size); + brush.build(editSession, target, current.getMaterial(), size); } catch (MaxChangedBlocksException e) { player.printError("Max blocks change limit reached."); // Never happens + } catch (MaxBrushRadiusException e) { + player.printError("Max brush radius exceeded: " + size + " > " + WorldEdit.getInstance().getConfiguration().maxBrushRadius); } finally { if (bag != null) { bag.flushChanges(); diff --git a/core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java b/core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java index 67a62c2f..00bda1f0 100644 --- a/core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java +++ b/core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java @@ -81,6 +81,11 @@ public class Expression { private final Functions functions = new Functions(); private ExpressionEnvironment environment; + public Expression(double constant) { + variableNames = null; + root = new Constant(0, constant); + } + public static Expression compile(String expression, String... variableNames) throws ExpressionException { return new Expression(expression, variableNames); } @@ -111,6 +116,9 @@ public class Expression { } public double evaluate(double... values) throws EvaluationException { + if (root instanceof Constant) { + return root.getValue(); + } for (int i = 0; i < values.length; i++) { Variable var = variableArray[i]; var.value = values[i]; @@ -125,6 +133,10 @@ public class Expression { } } + public RValue getRoot() { + return root; + } + public void optimize() throws EvaluationException { root = root.optimize(); }