mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-25 03:55:35 +01:00
Not finished yet (spline brush)
This commit is contained in:
parent
42a3203777
commit
5b96a52e99
@ -92,6 +92,8 @@ public enum BBC {
|
||||
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
|
||||
BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2).", "WorldEdit.Brush"),
|
||||
BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_LINE("Line brush shape equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_SPLINE("Line brush shape equipped (%s0). Right click to select points, left click to execute.", "WorldEdit.Brush"),
|
||||
BRUSH_BLEND_BALL("Blend ball brush equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_ERODE("Erode brush equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_PASTE_NONE("Nothing to paste", "WorldEdit.Brush"),
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.mask.RadiusMask;
|
||||
import com.boydti.fawe.object.visitor.DFSRecursiveVisitor;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
@ -16,9 +18,11 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
public class RecurseBrush implements Brush {
|
||||
|
||||
private final BrushTool tool;
|
||||
private final boolean dfs;
|
||||
|
||||
public RecurseBrush(BrushTool tool) {
|
||||
public RecurseBrush(BrushTool tool, boolean dfs) {
|
||||
this.tool = tool;
|
||||
this.dfs = dfs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -34,8 +38,28 @@ public class RecurseBrush implements Brush {
|
||||
}
|
||||
final BlockReplace replace = new BlockReplace(editSession, to);
|
||||
editSession.setMask((Mask) null);
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, radius);
|
||||
visitor.visit(position);
|
||||
Operations.completeBlindly(visitor);
|
||||
final int maxY = editSession.getMaxY();
|
||||
if (dfs) {
|
||||
final Mask radMask = new RadiusMask(0, (int) size);
|
||||
DFSRecursiveVisitor visitor = new DFSRecursiveVisitor(mask, replace, Integer.MAX_VALUE, Integer.MAX_VALUE) {
|
||||
@Override
|
||||
public boolean isVisitable(Vector from, Vector to) {
|
||||
int y = to.getBlockY();
|
||||
return y >= y && y < maxY && radMask.test(to) && super.isVisitable(from, to);
|
||||
}
|
||||
};
|
||||
visitor.visit(position);
|
||||
Operations.completeBlindly(visitor);
|
||||
} else {
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, radius) {
|
||||
@Override
|
||||
public boolean isVisitable(Vector from, Vector to) {
|
||||
int y = to.getBlockY();
|
||||
return y >= y && y < maxY && super.isVisitable(from, to);
|
||||
}
|
||||
};
|
||||
visitor.visit(position);
|
||||
Operations.completeBlindly(visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
187
core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java
Normal file
187
core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java
Normal file
@ -0,0 +1,187 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.object.mask.IdMask;
|
||||
import com.boydti.fawe.object.visitor.DFSRecursiveVisitor;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.MaskIntersection;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
import com.sk89q.worldedit.math.interpolation.Interpolation;
|
||||
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
|
||||
import com.sk89q.worldedit.math.interpolation.Node;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class SplineBrush implements DoubleActionBrush {
|
||||
|
||||
public static int MAX_POINTS = 15;
|
||||
private ArrayList<ArrayList<Vector>> positionSets;
|
||||
private int numSplines;
|
||||
|
||||
private final DoubleActionBrushTool tool;
|
||||
private final LocalSession session;
|
||||
private final Player player;
|
||||
|
||||
public SplineBrush(Player player, LocalSession session, DoubleActionBrushTool tool) {
|
||||
this.tool = tool;
|
||||
this.session = session;
|
||||
this.player = player;
|
||||
this.positionSets = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, final Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
Mask mask = tool.getMask();
|
||||
if (mask == null) {
|
||||
mask = new IdMask(editSession);
|
||||
} else {
|
||||
mask = new MaskIntersection(mask, new IdMask(editSession));
|
||||
}
|
||||
switch (action) {
|
||||
case PRIMARY: { // Right
|
||||
if (positionSets.size() >= MAX_POINTS) {
|
||||
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
|
||||
}
|
||||
final ArrayList<Vector> points = new ArrayList<>();
|
||||
DFSRecursiveVisitor visitor = new DFSRecursiveVisitor(mask, new RegionFunction() {
|
||||
@Override
|
||||
public boolean apply(Vector p) throws WorldEditException {
|
||||
points.add(new Vector(p));
|
||||
return true;
|
||||
}
|
||||
}, (int) size, 1);
|
||||
visitor.visit(position);
|
||||
Operations.completeBlindly(visitor);
|
||||
if (points.size() > numSplines) {
|
||||
numSplines = points.size();
|
||||
}
|
||||
this.positionSets.add(points);
|
||||
player.print("Added position, right click to spline them together!");
|
||||
break;
|
||||
}
|
||||
case SECONDARY: {
|
||||
if (positionSets.size() < 2) {
|
||||
player.print("Not enough positions set!");
|
||||
return;
|
||||
}
|
||||
List<Vector> centroids = new ArrayList<>();
|
||||
for (List<Vector> points : positionSets) {
|
||||
centroids.add(getCentroid(points));
|
||||
}
|
||||
|
||||
double tension = 0;
|
||||
double bias = 0;
|
||||
double continuity = 0;
|
||||
double quality = 10;
|
||||
|
||||
final List<Node> nodes = new ArrayList<Node>(centroids.size());
|
||||
|
||||
final Interpolation interpol = new KochanekBartelsInterpolation();
|
||||
for (final Vector nodevector : centroids) {
|
||||
final Node n = new Node(nodevector);
|
||||
n.setTension(tension);
|
||||
n.setBias(bias);
|
||||
n.setContinuity(continuity);
|
||||
nodes.add(n);
|
||||
}
|
||||
|
||||
Vector up = new Vector(0, 1, 0);
|
||||
AffineTransform transform = new AffineTransform();
|
||||
|
||||
// TODO index offset based on transform
|
||||
|
||||
int samples = numSplines;
|
||||
for (int i = 0; i < numSplines; i++) {
|
||||
List<Vector> currentSpline = new ArrayList<>();
|
||||
for (ArrayList<Vector> points : positionSets) {
|
||||
int listSize = points.size();
|
||||
int index = (int) (i * listSize / (double) (numSplines));
|
||||
currentSpline.add(points.get(index));
|
||||
}
|
||||
editSession.drawSpline(Patterns.wrap(pattern), currentSpline, 0, 0, 0, 10, 0, true);
|
||||
}
|
||||
player.print("Created spline");
|
||||
positionSets.clear();
|
||||
numSplines = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Vector getCentroid(Collection<Vector> points) {
|
||||
Vector sum = new Vector();
|
||||
for (Vector p : points) {
|
||||
sum.x += p.x;
|
||||
sum.y += p.y;
|
||||
sum.z += p.z;
|
||||
}
|
||||
return sum.multiply(1.0 / points.size());
|
||||
}
|
||||
|
||||
private Vector normal(Collection<Vector> points, Vector centroid) {
|
||||
int n = points.size();
|
||||
switch (n) {
|
||||
case 1: {
|
||||
return null;
|
||||
}
|
||||
case 2: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Calc full 3x3 covariance matrix, excluding symmetries:
|
||||
double xx = 0.0; double xy = 0.0; double xz = 0.0;
|
||||
double yy = 0.0; double yz = 0.0; double zz = 0.0;
|
||||
|
||||
Vector r = new Vector();
|
||||
for (Vector p : points) {
|
||||
r.x = p.x - centroid.x;
|
||||
r.y = p.y - centroid.y;
|
||||
r.z = p.z - centroid.z;
|
||||
xx += r.x * r.x;
|
||||
xy += r.x * r.y;
|
||||
xz += r.x * r.z;
|
||||
yy += r.y * r.y;
|
||||
yz += r.y * r.z;
|
||||
zz += r.z * r.z;
|
||||
}
|
||||
|
||||
double det_x = yy*zz - yz*yz;
|
||||
double det_y = xx*zz - xz*xz;
|
||||
double det_z = xx*yy - xy*xy;
|
||||
|
||||
double det_max = Math.max(Math.max(det_x, det_y), det_z);
|
||||
if (det_max <= 0.0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Pick path with best conditioning:
|
||||
Vector dir;
|
||||
if (det_max == det_x) {
|
||||
double a = (xz*yz - xy*zz) / det_x;
|
||||
double b = (xy*yz - xz*yy) / det_x;
|
||||
dir = new Vector(1.0, a, b);
|
||||
} else if (det_max == det_y) {
|
||||
double a = (yz*xz - xy*zz) / det_y;
|
||||
double b = (xy*xz - yz*xx) / det_y;
|
||||
dir = new Vector(a, 1.0, b);
|
||||
} else {
|
||||
double a = (yz*xy - xz*yy) / det_z;
|
||||
double b = (xz*xy - yz*xx) / det_z;
|
||||
dir = new Vector(a, b, 1.0);
|
||||
};
|
||||
return dir.normalize();
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.boydti.fawe.object.visitor;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* An implementation of an {@link com.sk89q.worldedit.function.visitor.BreadthFirstSearch} that uses a mask to
|
||||
* determine where a block should be visited.
|
||||
*/
|
||||
public class DFSRecursiveVisitor extends DFSVisitor {
|
||||
|
||||
private final Mask mask;
|
||||
|
||||
public DFSRecursiveVisitor(final Mask mask, final RegionFunction function) {
|
||||
this(mask, function, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new recursive visitor.
|
||||
*
|
||||
* @param mask the mask
|
||||
* @param function the function
|
||||
*/
|
||||
public DFSRecursiveVisitor(final Mask mask, final RegionFunction function, int maxDepth, int maxBranching) {
|
||||
super(function, maxDepth, maxBranching);
|
||||
checkNotNull(mask);
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisitable(final Vector from, final Vector to) {
|
||||
return this.mask.test(to);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return RecursiveVisitor.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,211 @@
|
||||
package com.boydti.fawe.object.visitor;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.IntegerTrio;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.RunContext;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class DFSVisitor implements Operation {
|
||||
|
||||
private final RegionFunction function;
|
||||
private final List<Vector> directions = new ArrayList<>();
|
||||
private final Map<Node, AtomicInteger> visited;
|
||||
private final ArrayDeque<NodePair> queue;
|
||||
private final HashSet<Node> hashQueue;
|
||||
private final int maxDepth;
|
||||
private final int maxBranch;
|
||||
private int affected = 0;
|
||||
|
||||
public DFSVisitor(final RegionFunction function) {
|
||||
this(function, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public DFSVisitor(final RegionFunction function, int maxDepth, int maxBranching) {
|
||||
this.queue = new ArrayDeque<>();
|
||||
this.hashQueue = new LinkedHashSet<>();
|
||||
this.visited = new LinkedHashMap<>();
|
||||
this.function = function;
|
||||
this.directions.add(new Vector(0, -1, 0));
|
||||
this.directions.add(new Vector(0, 1, 0));
|
||||
this.directions.add(new Vector(-1, 0, 0));
|
||||
this.directions.add(new Vector(1, 0, 0));
|
||||
this.directions.add(new Vector(0, 0, -1));
|
||||
this.directions.add(new Vector(0, 0, 1));
|
||||
this.maxDepth = maxDepth;
|
||||
this.maxBranch = maxBranching;
|
||||
}
|
||||
|
||||
public abstract boolean isVisitable(Vector from, Vector to);
|
||||
|
||||
public Collection<Vector> getDirections() {
|
||||
return this.directions;
|
||||
}
|
||||
|
||||
private IntegerTrio[] getIntDirections() {
|
||||
IntegerTrio[] array = new IntegerTrio[directions.size()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
Vector dir = directions.get(i);
|
||||
array[i] = new IntegerTrio(dir.getBlockX(), dir.getBlockY(), dir.getBlockZ());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void visit(final Vector pos) {
|
||||
Node node = new Node((int) pos.x, (int) pos.y, (int) pos.z);
|
||||
if (!this.hashQueue.contains(node)) {
|
||||
isVisitable(pos, pos); // Ignore this, just to initialize mask on this point
|
||||
queue.addFirst(new NodePair(null, node, 0));
|
||||
hashQueue.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
NodePair current;
|
||||
Node from;
|
||||
Node adjacent;
|
||||
Vector mutable = new Vector();
|
||||
Vector mutable2 = new Vector();
|
||||
int countAdd,countAttempt;
|
||||
IntegerTrio[] dirs = getIntDirections();
|
||||
|
||||
for (int layer = 0; !queue.isEmpty(); layer++) {
|
||||
current = queue.poll();
|
||||
from = current.to;
|
||||
hashQueue.remove(from);
|
||||
if (visited.containsKey(from)) {
|
||||
continue;
|
||||
}
|
||||
mutable.x = from.getX();
|
||||
mutable.y = from.getY();
|
||||
mutable.z = from.getZ();
|
||||
function.apply(mutable);
|
||||
countAdd = 0;
|
||||
countAttempt = 0;
|
||||
for (IntegerTrio direction : dirs) {
|
||||
mutable2.x = from.getX() + direction.x;
|
||||
mutable2.y = from.getY() + direction.y;
|
||||
mutable2.z = from.getZ() + direction.z;
|
||||
if (isVisitable(mutable, mutable2)) {
|
||||
adjacent = new Node(mutable2.getBlockX(), mutable2.getBlockY(), mutable2.getBlockZ());
|
||||
if ((current.from == null || !adjacent.equals(current.from))) {
|
||||
AtomicInteger adjacentCount = visited.get(adjacent);
|
||||
if (adjacentCount == null) {
|
||||
if (countAdd++ < maxBranch) {
|
||||
if (!hashQueue.contains(adjacent)) {
|
||||
if (current.depth == maxDepth) {
|
||||
countAttempt++;
|
||||
} else {
|
||||
hashQueue.add(adjacent);
|
||||
queue.addFirst(new NodePair(from, adjacent, current.depth + 1));
|
||||
}
|
||||
} else {
|
||||
countAttempt++;
|
||||
}
|
||||
} else {
|
||||
countAttempt++;
|
||||
}
|
||||
} else if (adjacentCount.decrementAndGet() == 0) {
|
||||
visited.remove(adjacent);
|
||||
} else if (hashQueue.contains(adjacent)) {
|
||||
countAttempt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (countAttempt > 0) {
|
||||
visited.put(from, new AtomicInteger(countAttempt));
|
||||
}
|
||||
affected++;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStatusMessages(List<String> messages) {
|
||||
messages.add(BBC.VISITOR_BLOCK.format(getAffected()));
|
||||
}
|
||||
|
||||
public int getAffected() {
|
||||
return this.affected;
|
||||
}
|
||||
|
||||
public class NodePair {
|
||||
public final Node to;
|
||||
public final Node from;
|
||||
private final int depth;
|
||||
|
||||
public NodePair(Node from, Node to, int depth) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.depth = depth;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Node {
|
||||
private int x,y,z;
|
||||
|
||||
public Node(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
private final void set(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
private final void set(Node node) {
|
||||
this.x = node.x;
|
||||
this.y = node.y;
|
||||
this.z = node.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return (x ^ (z << 12)) ^ (y << 24);
|
||||
}
|
||||
|
||||
private final int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
private final int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
private final int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return x + "," + y + "," + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
Node other = (Node) obj;
|
||||
return other.x == x && other.z == z && other.y == y;
|
||||
}
|
||||
}
|
||||
}
|
@ -102,7 +102,6 @@ import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.RValue;
|
||||
import com.sk89q.worldedit.math.interpolation.Interpolation;
|
||||
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
|
||||
import com.sk89q.worldedit.math.interpolation.Node;
|
||||
import com.sk89q.worldedit.math.noise.RandomNoise;
|
||||
@ -2684,7 +2683,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
Set<Vector> vset = new HashSet<Vector>();
|
||||
final List<Node> nodes = new ArrayList<Node>(nodevectors.size());
|
||||
|
||||
final Interpolation interpol = new KochanekBartelsInterpolation();
|
||||
final KochanekBartelsInterpolation interpol = new KochanekBartelsInterpolation();
|
||||
|
||||
for (final Vector nodevector : nodevectors) {
|
||||
final Node n = new Node(nodevector);
|
||||
@ -2701,7 +2700,6 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
final int tipx = (int) Math.round(tipv.getX());
|
||||
final int tipy = (int) Math.round(tipv.getY());
|
||||
final int tipz = (int) Math.round(tipv.getZ());
|
||||
|
||||
vset.add(new Vector(tipx, tipy, tipz));
|
||||
}
|
||||
|
||||
|
@ -24,14 +24,15 @@ import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.BlendBall;
|
||||
import com.boydti.fawe.object.brush.CommandBrush;
|
||||
import com.boydti.fawe.object.brush.CopyPastaBrush;
|
||||
import com.boydti.fawe.object.brush.HeightBrush;
|
||||
import com.boydti.fawe.object.brush.BlendBall;
|
||||
import com.boydti.fawe.object.brush.DoubleActionBrushTool;
|
||||
import com.boydti.fawe.object.brush.ErodeBrush;
|
||||
import com.boydti.fawe.object.brush.HeightBrush;
|
||||
import com.boydti.fawe.object.brush.LineBrush;
|
||||
import com.boydti.fawe.object.brush.RecurseBrush;
|
||||
import com.boydti.fawe.object.brush.SplineBrush;
|
||||
import com.boydti.fawe.object.mask.IdMask;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
@ -123,16 +124,17 @@ public class BrushCommands {
|
||||
aliases = { "recursive", "recurse", "r" },
|
||||
usage = "<pattern-to> [radius]",
|
||||
desc = "Choose the recursive brush",
|
||||
help = "Chooses the recursive brush",
|
||||
help = "Chooses the recursive brush\n" +
|
||||
"The -d flag Will apply in depth first order",
|
||||
min = 0,
|
||||
max = 2
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.recursive")
|
||||
public void recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("2") double radius) throws WorldEditException {
|
||||
public void recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("2") double radius, @Switch('d') boolean depthFirst) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setSize(radius);
|
||||
tool.setBrush(new RecurseBrush(tool), "worldedit.brush.recursive");
|
||||
tool.setBrush(new RecurseBrush(tool, depthFirst), "worldedit.brush.recursive");
|
||||
tool.setMask(new IdMask(editSession));
|
||||
tool.setFill(fill);
|
||||
BBC.BRUSH_SPHERE.send(player, radius);
|
||||
@ -158,7 +160,25 @@ public class BrushCommands {
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line");
|
||||
BBC.BRUSH_SPHERE.send(player, radius);
|
||||
BBC.BRUSH_LINE.send(player, radius);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "spline", "spl" },
|
||||
usage = "<pattern>",
|
||||
desc = "Choose the spline brush",
|
||||
help = "Chooses the spline brush",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.spline")
|
||||
public void splineBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("25") double radius) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
tool.setBrush(new SplineBrush(player, session, tool), "worldedit.brush.spline");
|
||||
BBC.BRUSH_SPLINE.send(player, radius);
|
||||
}
|
||||
|
||||
@Command(
|
||||
|
@ -67,7 +67,6 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
|
||||
@Override
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
Node from;
|
||||
Node adjacent;
|
||||
Vector mutable = new Vector();
|
||||
@ -143,7 +142,7 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
|
||||
public Node(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = (short) y;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@ -157,7 +156,7 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
|
||||
private final void set(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = (short) y;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user