diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index 67ebfa7b1..042773e1a 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -2642,4 +2642,33 @@ public class EditSession { return shape.generate(this, pattern, hollow); } + + public int deformRegion(final Region region, final Vector zero, final Vector unit, final String expressionString) throws ExpressionException, MaxChangedBlocksException { + final Expression expression = Expression.compile(expressionString, "x", "y", "z"); + expression.optimize(); + + final RValue x = expression.getVariable("x"); + final RValue y = expression.getVariable("y"); + final RValue z = expression.getVariable("z"); + + int affected = 0; + + for (BlockVector position : region) { + final Vector scaled = position.subtract(zero).divide(unit); + + expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ()); + + final Vector sourceScaled = new Vector(x.getValue(), y.getValue(), z.getValue()); + + final BlockVector sourcePosition = sourceScaled.multiply(unit).add(zero).toBlockPoint(); + + BaseBlock material = new BaseBlock(world.getBlockType(sourcePosition), world.getBlockData(sourcePosition)); + + if (setBlock(position, material)) { + ++affected; + } + } + + return affected; + } } diff --git a/src/main/java/com/sk89q/worldedit/commands/RegionCommands.java b/src/main/java/com/sk89q/worldedit/commands/RegionCommands.java index 24aa75454..53d100ce8 100644 --- a/src/main/java/com/sk89q/worldedit/commands/RegionCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/RegionCommands.java @@ -29,6 +29,7 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.*; import com.sk89q.worldedit.*; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.expression.ExpressionException; import com.sk89q.worldedit.filtering.GaussianKernel; import com.sk89q.worldedit.filtering.HeightMapFilter; import com.sk89q.worldedit.masks.Mask; @@ -325,4 +326,48 @@ public class RegionCommands { session.setMask(mask); player.print("Region regenerated."); } + + @Command( + aliases = { "/deform" }, + usage = "", + desc = "Deforms a selected region with an expression", + flags = "ro", + min = 1, + max = -1 + ) + @CommandPermissions("worldedit.region.deform") + @Logging(ALL) + public static void deform(CommandContext args, WorldEdit we, + LocalSession session, LocalPlayer player, EditSession editSession) + throws WorldEditException { + + final Region region = session.getSelection(player.getWorld()); + + final String expression = args.getJoinedStrings(0); + + final Vector zero; + final Vector unit; + + if (args.hasFlag('r')) { + zero = new Vector(0,0,0); + unit = new Vector(1,1,1); + } else if (args.hasFlag('o')) { + zero = session.getPlacementPosition(player); + unit = new Vector(1,1,1); + } else { + final Vector min = region.getMinimumPoint(); + final Vector max = region.getMaximumPoint(); + + zero = max.add(min).multiply(0.5); + unit = max.subtract(zero); + } + + try { + final int affected = editSession.deformRegion(region, zero, unit, expression); + player.findFreePosition(); + player.print(affected + " block(s) have been deformed."); + } catch (ExpressionException e) { + player.printError(e.getMessage()); + } + } }