Heightmap rotation

This commit is contained in:
Jesse Boyd 2017-03-11 17:16:10 +11:00
parent cf0bd96308
commit fb76ff4ea0
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
11 changed files with 343 additions and 150 deletions

View File

@ -28,7 +28,7 @@ ext {
date = git.head().date.format("yy.MM.dd") date = git.head().date.format("yy.MM.dd")
revision = "-${git.head().abbreviatedId}" revision = "-${git.head().abbreviatedId}"
parents = git.head().parentIds; parents = git.head().parentIds;
index = -87; // Offset to mach CI index = -88; // Offset to mach CI
int major, minor, patch; int major, minor, patch;
major = minor = patch = 0; major = minor = patch = 0;
for (;parents != null && !parents.isEmpty();index++) { for (;parents != null && !parents.isEmpty();index++) {

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.object.brush.heightmap.HeightMap;
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap; import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
@ -23,7 +24,8 @@ public class FlattenBrush extends HeightBrush {
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null; mask = null;
} }
heightMap.setSize(size); HeightMap map = getHeightMap();
heightMap.perform(editSession, mask, position, size, rotation, yscale, true, true); map.setSize(size);
map.perform(editSession, mask, position, size, rotation, yscale, true, true);
} }
} }

View File

@ -1,6 +1,9 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.brush.heightmap.HeightMap;
import com.boydti.fawe.object.brush.heightmap.RotatableHeightMap;
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap; import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
@ -16,7 +19,8 @@ import java.io.InputStream;
public class HeightBrush implements Brush { public class HeightBrush implements Brush {
public final ScalableHeightMap heightMap; private HeightMap heightMap;
private boolean randomRotate;
public final int rotation; public final int rotation;
public final double yscale; public final double yscale;
@ -40,6 +44,21 @@ public class HeightBrush implements Brush {
} }
} }
public HeightMap getHeightMap() {
if (randomRotate) {
if (!(heightMap instanceof RotatableHeightMap)) {
heightMap = new RotatableHeightMap(heightMap);
}
RotatableHeightMap rotatable = (RotatableHeightMap) heightMap;
rotatable.rotate(PseudoRandom.random.nextInt(360));
}
return heightMap;
}
public void setRandomRotate(boolean randomRotate) {
this.randomRotate = randomRotate;
}
@Override @Override
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
int size = (int) sizeDouble; int size = (int) sizeDouble;
@ -47,7 +66,8 @@ public class HeightBrush implements Brush {
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null; mask = null;
} }
heightMap.setSize(size); HeightMap map = getHeightMap();
heightMap.perform(editSession, mask, position, size, rotation, yscale, true, false); map.setSize(size);
map.perform(editSession, mask, position, size, rotation, yscale, true, false);
} }
} }

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.brush.heightmap.HeightMap;
import com.boydti.fawe.object.mask.AdjacentAnyMask; import com.boydti.fawe.object.mask.AdjacentAnyMask;
import com.boydti.fawe.object.mask.RadiusMask; import com.boydti.fawe.object.mask.RadiusMask;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
@ -11,10 +12,12 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.RegionMask;
import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RecursiveVisitor; import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import com.sk89q.worldedit.regions.CuboidRegion;
import java.io.InputStream; import java.io.InputStream;
import java.util.Arrays; import java.util.Arrays;
@ -35,21 +38,23 @@ public class StencilBrush extends HeightBrush {
int maxY = editSession.getMaxY(); int maxY = editSession.getMaxY();
double scale = (yscale / sizeDouble) * (maxY + 1); double scale = (yscale / sizeDouble) * (maxY + 1);
heightMap.setSize(size); final HeightMap map = getHeightMap();
map.setSize(size);
int cutoff = onlyWhite ? maxY : 0; int cutoff = onlyWhite ? maxY : 0;
final AdjacentAnyMask adjacent = new AdjacentAnyMask(editSession, Arrays.asList(new BaseBlock(0))); final AdjacentAnyMask adjacent = new AdjacentAnyMask(editSession, Arrays.asList(new BaseBlock(0)));
final SolidBlockMask solid = new SolidBlockMask(editSession); final SolidBlockMask solid = new SolidBlockMask(editSession);
RegionMask region = new RegionMask(new CuboidRegion(position.subtract(size, size, size), position.add(size, size, size)));
final RadiusMask radius = new RadiusMask(0, size); final RadiusMask radius = new RadiusMask(0, size);
RecursiveVisitor visitor = new RecursiveVisitor(new Mask() { RecursiveVisitor visitor = new RecursiveVisitor(new Mask() {
@Override @Override
public boolean test(Vector vector) { public boolean test(Vector vector) {
if (solid.test(vector) && radius.test(vector)) { if (solid.test(vector) && radius.test(vector)) {
int dx = vector.getBlockX() - cx;
int dy = vector.getBlockY() - cy;
int dz = vector.getBlockZ() - cz;
Vector dir = adjacent.direction(vector); Vector dir = adjacent.direction(vector);
if (dir != null) { if (dir != null) {
int dx = vector.getBlockX() - cx;
int dy = vector.getBlockY() - cy;
int dz = vector.getBlockZ() - cz;
if (dy != 0) { if (dy != 0) {
if (dir.getBlockX() != 0) { if (dir.getBlockX() != 0) {
dx += dir.getBlockX() * dy; dx += dir.getBlockX() * dy;
@ -57,7 +62,7 @@ public class StencilBrush extends HeightBrush {
dz += dir.getBlockZ() * dy; dz += dir.getBlockZ() * dy;
} }
} }
double raise = heightMap.getHeight(dx, dz); double raise = map.getHeight(dx, dz);
int val = (int) Math.ceil(raise * scale); int val = (int) Math.ceil(raise * scale);
if (val <= cutoff) { if (val <= cutoff) {
return true; return true;

View File

@ -0,0 +1,20 @@
package com.boydti.fawe.object.brush.heightmap;
public class AbstractDelegateHeightMap implements HeightMap {
private final HeightMap parent;
public AbstractDelegateHeightMap(HeightMap parent) {
this.parent = parent;
}
@Override
public double getHeight(int x, int z) {
return parent.getHeight(x, z);
}
@Override
public void setSize(int size) {
parent.setSize(size);
}
}

View File

@ -0,0 +1,132 @@
package com.boydti.fawe.object.brush.heightmap;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.util.MainUtil;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.math.convolution.GaussianKernel;
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
public interface HeightMap {
public double getHeight(int x, int z);
public void setSize(int size);
default void perform(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
int[] data = generateHeightData(session, mask, pos, size, rotationMode, yscale, smooth, towards);
applyHeightMapData(data, session, mask, pos, size, rotationMode, yscale, smooth, towards);
}
default void applyHeightMapData(int[] data, EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
Vector top = session.getMaximumPoint();
int maxY = top.getBlockY();
int diameter = 2 * size + 1;
int iterations = 1;
WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, maxY, size));
Vector max = pos.add(size, maxY, size);
Region region = new CuboidRegion(session.getWorld(), min, max);
com.sk89q.worldedit.math.convolution.HeightMap heightMap = new com.sk89q.worldedit.math.convolution.HeightMap(session, region, false);
if (smooth) {
try {
HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
data = filter.filter(data, diameter, diameter);
} catch (Throwable e) {
MainUtil.handleError(e);
}
}
heightMap.apply(data);
}
default int[] generateHeightData(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) {
Vector top = session.getMaximumPoint();
int maxY = top.getBlockY();
int diameter = 2 * size + 1;
int centerX = pos.getBlockX();
int centerZ = pos.getBlockZ();
int centerY = pos.getBlockY();
int endY = pos.getBlockY() + size;
int startY = pos.getBlockY() - size;
int[] newData = new int[diameter * diameter];
Vector mutablePos = new Vector(0, 0, 0);
if (towards) {
double sizePow = Math.pow(size, yscale);
int targetY = pos.getBlockY();
for (int x = -size; x <= size; x++) {
int xx = centerX + x;
mutablePos.mutX(xx);
for (int z = -size; z <= size; z++) {
int index = (z + size) * diameter + (x + size);
int zz = centerZ + z;
double raise;
switch (rotationMode) {
default:
raise = getHeight(x, z);
break;
case 1:
raise = getHeight(z, x);
break;
case 2:
raise = getHeight(-x, -z);
break;
case 3:
raise = getHeight(-z, -x);
break;
}
int height = session.getNearestSurfaceTerrainBlock(xx, zz, pos.getBlockY(), 0, 255);
if (height == 0) {
newData[index] = centerY;
continue;
}
double raisePow = Math.pow(raise, yscale);
int diff = targetY - height;
double raiseScaled = diff * (raisePow / sizePow);
double raiseScaledAbs = Math.abs(raiseScaled);
int random = PseudoRandom.random.random(256) < (int) ((Math.ceil(raiseScaledAbs) - Math.floor(raiseScaledAbs)) * 256) ? (diff > 0 ? 1 : -1) : 0;
int raiseScaledInt = (int) raiseScaled + random;
newData[index] = height + raiseScaledInt;
}
}
} else {
for (int x = -size; x <= size; x++) {
int xx = centerX + x;
mutablePos.mutX(xx);
for (int z = -size; z <= size; z++) {
int index = (z + size) * diameter + (x + size);
int zz = centerZ + z;
double raise;
switch (rotationMode) {
default:
raise = getHeight(x, z);
break;
case 1:
raise = getHeight(z, x);
break;
case 2:
raise = getHeight(-x, -z);
break;
case 3:
raise = getHeight(-z, -x);
break;
}
int height = session.getNearestSurfaceTerrainBlock(xx, zz, pos.getBlockY(), 0, maxY);
if (height == 0) {
newData[index] = centerY;
continue;
}
raise = (yscale * raise);
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raise - (int) raise) * (maxY + 1)) ? 1 : 0;
int newHeight = height + (int) raise + random;
newData[index] = newHeight;
}
}
}
return newData;
}
}

View File

@ -0,0 +1,28 @@
package com.boydti.fawe.object.brush.heightmap;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.math.transform.AffineTransform;
public class RotatableHeightMap extends AbstractDelegateHeightMap {
private AffineTransform transform;
private MutableBlockVector mutable;
public RotatableHeightMap(HeightMap parent) {
super(parent);
mutable = new MutableBlockVector();
this.transform = new AffineTransform();
}
public void rotate(double angle) {
this.transform = transform.rotateY(angle);
}
@Override
public double getHeight(int x, int z) {
mutable.mutX(x);
mutable.mutZ(z);
Vector pos = transform.apply(mutable.setComponents(x, 0, z));
return super.getHeight(pos.getBlockX(), pos.getBlockZ());
}
}

View File

@ -1,22 +1,11 @@
package com.boydti.fawe.object.brush.heightmap; package com.boydti.fawe.object.brush.heightmap;
import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.math.convolution.GaussianKernel;
import com.sk89q.worldedit.math.convolution.HeightMap;
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.Raster; import java.awt.image.Raster;
import java.io.IOException; import java.io.IOException;
@ -24,7 +13,7 @@ import java.io.InputStream;
import java.util.HashSet; import java.util.HashSet;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
public class ScalableHeightMap { public class ScalableHeightMap implements com.boydti.fawe.object.brush.heightmap.HeightMap{
public int size2; public int size2;
public int size; public int size;
@ -41,11 +30,13 @@ public class ScalableHeightMap {
setSize(size); setSize(size);
} }
@Override
public void setSize(int size) { public void setSize(int size) {
this.size = size; this.size = size;
this.size2 = size * size; this.size2 = size * size;
} }
@Override
public double getHeight(int x, int z) { public double getHeight(int x, int z) {
int dx = Math.abs(x); int dx = Math.abs(x);
int dz = Math.abs(z); int dz = Math.abs(z);
@ -117,115 +108,4 @@ public class ScalableHeightMap {
} }
return new ArrayHeightMap(array); return new ArrayHeightMap(array);
} }
public void perform(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
int[] data = generateHeightData(session, mask, pos, size, rotationMode, yscale, smooth, towards);
applyHeightMapData(data, session, mask, pos, size, rotationMode, yscale, smooth, towards);
}
public void applyHeightMapData(int[] data, EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
Vector top = session.getMaximumPoint();
int maxY = top.getBlockY();
int diameter = 2 * size + 1;
int iterations = 1;
WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, maxY, size));
Vector max = pos.add(size, maxY, size);
Region region = new CuboidRegion(session.getWorld(), min, max);
HeightMap heightMap = new HeightMap(session, region, false);
if (smooth) {
try {
HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
data = filter.filter(data, diameter, diameter);
} catch (Throwable e) {
MainUtil.handleError(e);
}
}
heightMap.apply(data);
}
public int[] generateHeightData(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) {
Vector top = session.getMaximumPoint();
int maxY = top.getBlockY();
int diameter = 2 * size + 1;
int centerX = pos.getBlockX();
int centerZ = pos.getBlockZ();
int centerY = pos.getBlockY();
int endY = pos.getBlockY() + size;
int startY = pos.getBlockY() - size;
int[] newData = new int[diameter * diameter];
Vector mutablePos = new Vector(0, 0, 0);
if (towards) {
double sizePow = Math.pow(size, yscale);
int targetY = pos.getBlockY();
for (int x = -size; x <= size; x++) {
int xx = centerX + x;
mutablePos.mutX(xx);
for (int z = -size; z <= size; z++) {
int index = (z + size) * diameter + (x + size);
int zz = centerZ + z;
double raise;
switch (rotationMode) {
default:
raise = getHeight(x, z);
break;
case 1:
raise = getHeight(z, x);
break;
case 2:
raise = getHeight(-x, -z);
break;
case 3:
raise = getHeight(-z, -x);
break;
}
int height = session.getNearestSurfaceTerrainBlock(xx, zz, pos.getBlockY(), 0, 255);
if (height == 0) {
newData[index] = centerY;
continue;
}
double raisePow = Math.pow(raise, yscale);
int diff = targetY - height;
double raiseScaled = diff * (raisePow / sizePow);
double raiseScaledAbs = Math.abs(raiseScaled);
int random = PseudoRandom.random.random(256) < (int) ((Math.ceil(raiseScaledAbs) - Math.floor(raiseScaledAbs)) * 256) ? (diff > 0 ? 1 : -1) : 0;
int raiseScaledInt = (int) raiseScaled + random;
newData[index] = height + raiseScaledInt;
}
}
} else {
for (int x = -size; x <= size; x++) {
int xx = centerX + x;
mutablePos.mutX(xx);
for (int z = -size; z <= size; z++) {
int index = (z + size) * diameter + (x + size);
int zz = centerZ + z;
double raise;
switch (rotationMode) {
default:
raise = getHeight(x, z);
break;
case 1:
raise = getHeight(z, x);
break;
case 2:
raise = getHeight(-x, -z);
break;
case 3:
raise = getHeight(-z, -x);
break;
}
int height = session.getNearestSurfaceTerrainBlock(xx, zz, pos.getBlockY(), 0, maxY);
if (height == 0) {
newData[index] = centerY;
continue;
}
raise = (yscale * raise);
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raise - (int) raise) * (maxY + 1)) ? 1 : 0;
int newHeight = height + (int) raise + random;
newData[index] = newHeight;
}
}
}
return newData;
}
} }

View File

@ -0,0 +1,39 @@
package com.boydti.fawe.object.extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.biome.BaseBiome;
public class OffsetExtent extends ResettableExtent {
private final int dx, dy, dz;
public OffsetExtent(Extent parent, int dx, int dy, int dz) {
super(parent);
this.dx = dx;
this.dy = dy;
this.dz = dz;
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
return super.setBiome(new Vector2D(position.getBlockX() + dx, position.getBlockZ() + dz), biome);
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
return super.setBlock(location.getBlockX() + dx, location.getBlockY() + dy, location.getBlockZ() + dz, block);
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
return super.setBlock(x + dx, y + dy, z + dz, block);
}
@Override
public ResettableExtent setExtent(Extent extent) {
return super.setExtent(extent);
}
}

View File

@ -1453,7 +1453,65 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
checkArgument(depth >= 1, "depth >= 1"); checkArgument(depth >= 1, "depth >= 1");
final MaskIntersection mask = new MaskIntersection(new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))), new BoundedHeightMask(Math.max( 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))); (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, Patterns.wrap(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();
}
public int fillDirection(final Vector origin, PlayerDirection direction, final Pattern pattern, final double radius, final int depth, final boolean recursive) throws MaxChangedBlocksException {
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 // Want to replace blocks
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));

View File

@ -542,18 +542,22 @@ public class BrushCommands {
max = -1 max = -1
) )
@CommandPermissions("worldedit.brush.stencil") @CommandPermissions("worldedit.brush.stencil")
public void stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite) throws WorldEditException { public void stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player); BrushTool tool = session.getBrushTool(player);
InputStream stream = getHeightmapStream(filename); InputStream stream = getHeightmapStream(filename);
tool.setFill(fill); tool.setFill(fill);
tool.setSize(radius); tool.setSize(radius);
HeightBrush brush;
try { try {
tool.setBrush(new StencilBrush(stream, rotation, yscale, onlyWhite, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height", player); brush = new StencilBrush(stream, rotation, yscale, onlyWhite, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null);
} catch (EmptyClipboardException ignore) { } catch (EmptyClipboardException ignore) {
tool.setBrush(new StencilBrush(stream, rotation, yscale, onlyWhite, null), "worldedit.brush.height", player); brush = new StencilBrush(stream, rotation, yscale, onlyWhite, null);
}
tool.setBrush(brush, "worldedit.brush.height", player);
if (randomRotate) {
brush.setRandomRotate(true);
} }
player.print(BBC.getPrefix() + BBC.BRUSH_STENCIL.f(radius)); player.print(BBC.getPrefix() + BBC.BRUSH_STENCIL.f(radius));
} }
@ -695,8 +699,8 @@ public class BrushCommands {
max = 4 max = 4
) )
@CommandPermissions("worldedit.brush.height") @CommandPermissions("worldedit.brush.height")
public void heightBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale) throws WorldEditException { public void heightBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate) throws WorldEditException {
terrainBrush(player, session, radius, filename, rotation, yscale, false, ScalableHeightMap.Shape.CONE); terrainBrush(player, session, radius, filename, rotation, yscale, false, randomRotate, ScalableHeightMap.Shape.CONE);
} }
@Command( @Command(
@ -710,8 +714,8 @@ public class BrushCommands {
max = 4 max = 4
) )
@CommandPermissions("worldedit.brush.height") @CommandPermissions("worldedit.brush.height")
public void cliffBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale) throws WorldEditException { public void cliffBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate) throws WorldEditException {
terrainBrush(player, session, radius, filename, rotation, yscale, true, ScalableHeightMap.Shape.CYLINDER); terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, ScalableHeightMap.Shape.CYLINDER);
} }
@Command( @Command(
@ -725,8 +729,8 @@ public class BrushCommands {
max = 4 max = 4
) )
@CommandPermissions("worldedit.brush.height") @CommandPermissions("worldedit.brush.height")
public void flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale) throws WorldEditException { public void flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate) throws WorldEditException {
terrainBrush(player, session, radius, filename, rotation, yscale, true, ScalableHeightMap.Shape.CONE); terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, ScalableHeightMap.Shape.CONE);
} }
private InputStream getHeightmapStream(String filename) { private InputStream getHeightmapStream(String filename) {
@ -760,24 +764,29 @@ public class BrushCommands {
return null; return null;
} }
private void terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, ScalableHeightMap.Shape shape) throws WorldEditException { private void terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, boolean randomRotate, ScalableHeightMap.Shape shape) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(radius);
InputStream stream = getHeightmapStream(filename); InputStream stream = getHeightmapStream(filename);
BrushTool tool = session.getBrushTool(player); BrushTool tool = session.getBrushTool(player);
tool.setSize(radius); tool.setSize(radius);
HeightBrush brush;
if (flat) { if (flat) {
try { try {
tool.setBrush(new FlattenBrush(stream, rotation, yscale, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null, shape), "worldedit.brush.height", player); brush = new FlattenBrush(stream, rotation, yscale, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null, shape);
} catch (EmptyClipboardException ignore) { } catch (EmptyClipboardException ignore) {
tool.setBrush(new FlattenBrush(stream, rotation, yscale, null, shape), "worldedit.brush.height", player); brush = new FlattenBrush(stream, rotation, yscale, null, shape);
} }
} else { } else {
try { try {
tool.setBrush(new HeightBrush(stream, rotation, yscale, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height", player); brush = new HeightBrush(stream, rotation, yscale, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null);
} catch (EmptyClipboardException ignore) { } catch (EmptyClipboardException ignore) {
tool.setBrush(new HeightBrush(stream, rotation, yscale, null), "worldedit.brush.height", player); brush = new HeightBrush(stream, rotation, yscale, null);
} }
} }
tool.setBrush(brush, "worldedit.brush.height", player);
if (randomRotate) {
brush.setRandomRotate(true);
}
player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius)); player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
} }