Add direction argument to fill

This commit is contained in:
Jesse Boyd 2017-08-21 00:40:10 +10:00
parent 65442c886a
commit 803c84a621
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
3 changed files with 130 additions and 72 deletions

View File

@ -106,6 +106,7 @@ import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.util.RegionOffset;
import com.sk89q.worldedit.function.visitor.DirectionalVisitor;
import com.sk89q.worldedit.function.visitor.DownwardVisitor;
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
import com.sk89q.worldedit.function.visitor.LayerVisitor;
@ -1446,6 +1447,43 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return this.changes;
}
/**
* Fills an area recursively in the X/Z directions.
*
* @param origin the location to start from
* @param pattern the block to fill with
* @param radius the radius of the spherical area to fill
* @param depth the maximum depth, starting from the origin
* @param direction the direction to fill
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int fillDirection(final Vector origin, final Pattern pattern, final double radius, final int depth, Vector direction) {
checkNotNull(origin);
checkNotNull(pattern);
checkArgument(radius >= 0, "radius >= 0");
checkArgument(depth >= 1, "depth >= 1");
initTransform(origin);
if (direction.equals(new Vector(0, -1, 0))) {
System.out.println("Fill down");
return fillXZ(origin, pattern, radius, depth, false);
}
final MaskIntersection mask = new MaskIntersection(new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))), Masks.negate(new ExistingBlockMask(EditSession.this)));
// Want to replace blocks
final BlockReplace replace = new BlockReplace(EditSession.this, pattern);
// Pick how we're going to visit blocks
RecursiveVisitor visitor = new DirectionalVisitor(mask, replace, origin, direction, (int) (radius * 2 + 1), this);
// Start at the origin
visitor.visit(origin);
// Execute
Operations.completeBlindly(visitor);
return this.changes = visitor.getAffected();
}
/**
* Fills an area recursively in the X/Z directions.
*
@ -1502,64 +1540,6 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return this.changes = visitor.getAffected();
}
// public int fillDirection(final Vector origin, PlayerDirection direction, final Pattern pattern, final double radius, final int depth, final boolean recursive) {
// checkNotNull(origin);
// checkNotNull(pattern);
// checkArgument(radius >= 0, "radius >= 0");
// checkArgument(depth >= 1, "depth >= 1");
//
// Vector dirVec = direction.vector();
// BlockVector min = origin.toBlockVector();
// BlockVector max = origin.toBlockVector();
//
// CuboidRegion cuboid = new CuboidRegion(new Vector(), new Vector());
// switch (direction) {
// case NORTH:
// break;
// case NORTH_EAST:
// break;
// case EAST:
// break;
// case SOUTH_EAST:
// break;
// case SOUTH:
// break;
// case SOUTH_WEST:
// break;
// case WEST:
// break;
// case NORTH_WEST:
// break;
// case UP:
// break;
// case DOWN:
// break;
// }
//
//
//
// final MaskIntersection mask = new MaskIntersection(new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))), new BoundedHeightMask(Math.max(
// (origin.getBlockY() - depth) + 1, 0), Math.min(EditSession.this.getMaximumPoint().getBlockY(), origin.getBlockY())), Masks.negate(new ExistingBlockMask(EditSession.this)));
//
// // Want to replace blocks
// final BlockReplace replace = new BlockReplace(EditSession.this, pattern);
//
// // Pick how we're going to visit blocks
// RecursiveVisitor visitor;
// if (recursive) {
// visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), this);
// } else {
// visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1), this);
// }
//
// // Start at the origin
// visitor.visit(origin);
//
// // Execute
// Operations.completeBlindly(visitor);
// return this.changes = visitor.getAffected();
// }
/**
* Remove a cuboid above the given position with a given apothem and a given height.
*

View File

@ -57,6 +57,7 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.EntityVisitor;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
@ -175,19 +176,15 @@ public class UtilityCommands extends MethodCommands {
usage = "<pattern> <radius> [depth]",
desc = "Fill a hole",
min = 2,
max = 3
max = 4
)
@CommandPermissions("worldedit.fill")
@Logging(PLACEMENT)
public void fill(Player player, LocalSession session, EditSession editSession, Pattern pattern, double radius, @Optional("1") double depth) throws WorldEditException {
public void fill(Player player, LocalSession session, EditSession editSession, Pattern pattern, double radius, @Optional("1") double depth, @Optional("down") @Direction Vector direction) throws WorldEditException {
worldEdit.checkMaxRadius(radius);
Vector pos = session.getPlacementPosition(player);
int affected = 0;
if (pattern instanceof BaseBlock) {
affected = editSession.fillXZ(pos, ((BaseBlock) pattern), radius, (int) depth, false);
} else {
affected = editSession.fillXZ(pos, pattern, radius, (int) depth, false);
}
int affected;
affected = editSession.fillDirection(pos, pattern, radius, (int) depth, direction);
player.print(BBC.getPrefix() + affected + " block(s) have been created.");
}
@ -203,12 +200,7 @@ public class UtilityCommands extends MethodCommands {
public void fillr(Player player, LocalSession session, EditSession editSession, Pattern pattern, double radius, @Optional("1") double depth) throws WorldEditException {
worldEdit.checkMaxRadius(radius);
Vector pos = session.getPlacementPosition(player);
int affected;
if (pattern instanceof BaseBlock) {
affected = editSession.fillXZ(pos, ((BaseBlock) pattern), radius, (int) depth, true);
} else {
affected = editSession.fillXZ(pos, pattern, radius, (int) depth, true);
}
int affected = editSession.fillXZ(pos, pattern, radius, (int) depth, true);
player.print(BBC.getPrefix() + affected + " block(s) have been created.");
}

View File

@ -0,0 +1,86 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.function.visitor;
import com.boydti.fawe.object.HasFaweQueue;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.mask.Mask;
import java.util.Collection;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Visits adjacent points on the same X-Z plane as long as the points
* pass the given mask, and then executes the provided region
* function on the entire column.
* <p>
* <p>This is used by {@code //fill}.</p>
*/
public class DirectionalVisitor extends RecursiveVisitor {
private final Vector origin;
private final Vector dirVec;
public DirectionalVisitor(Mask mask, RegionFunction function, Vector origin, Vector direction) {
this(mask, function, origin, direction, Integer.MAX_VALUE, null);
}
public DirectionalVisitor(Mask mask, RegionFunction function, Vector origin, Vector direction, int distance, HasFaweQueue hasFaweQueue) {
super(mask, function, distance, hasFaweQueue);
checkNotNull(mask);
this.origin = origin;
this.dirVec = new MutableBlockVector(direction);
final Collection<Vector> directions = this.getDirections();
directions.clear();
directions.add(new Vector(1, 0, 0));
directions.add(new Vector(-1, 0, 0));
directions.add(new Vector(0, 0, 1));
directions.add(new Vector(0, 0, -1));
directions.add(new Vector(0, -1, 0));
directions.add(new Vector(0, 1, 0));
}
@Override
public boolean isVisitable(final Vector from, final Vector to) {
int dx = to.getBlockX() - from.getBlockX();
int dz = to.getBlockZ() - from.getBlockZ();
int dy = to.getBlockY() - from.getBlockY();
if (dx != 0) {
if (dirVec.getBlockX() != 0 && dirVec.getBlockX() != dx) {
return false;
}
}
if (dy != 0) {
if (dirVec.getBlockY() != 0 && dirVec.getBlockY() != dy) {
return false;
}
}
if (dz != 0) {
if (dirVec.getBlockZ() != 0 && dirVec.getBlockZ() != dz) {
return false;
}
}
return super.isVisitable(from, to);
}
}