mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 21:56:33 +01:00
Heightmap rotation
This commit is contained in:
parent
cf0bd96308
commit
fb76ff4ea0
@ -28,7 +28,7 @@ ext {
|
||||
date = git.head().date.format("yy.MM.dd")
|
||||
revision = "-${git.head().abbreviatedId}"
|
||||
parents = git.head().parentIds;
|
||||
index = -87; // Offset to mach CI
|
||||
index = -88; // Offset to mach CI
|
||||
int major, minor, patch;
|
||||
major = minor = patch = 0;
|
||||
for (;parents != null && !parents.isEmpty();index++) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.brush.heightmap.HeightMap;
|
||||
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
@ -23,7 +24,8 @@ public class FlattenBrush extends HeightBrush {
|
||||
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
|
||||
mask = null;
|
||||
}
|
||||
heightMap.setSize(size);
|
||||
heightMap.perform(editSession, mask, position, size, rotation, yscale, true, true);
|
||||
HeightMap map = getHeightMap();
|
||||
map.setSize(size);
|
||||
map.perform(editSession, mask, position, size, rotation, yscale, true, true);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
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.exception.FaweException;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
@ -16,7 +19,8 @@ import java.io.InputStream;
|
||||
|
||||
public class HeightBrush implements Brush {
|
||||
|
||||
public final ScalableHeightMap heightMap;
|
||||
private HeightMap heightMap;
|
||||
private boolean randomRotate;
|
||||
public final int rotation;
|
||||
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
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
int size = (int) sizeDouble;
|
||||
@ -47,7 +66,8 @@ public class HeightBrush implements Brush {
|
||||
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
|
||||
mask = null;
|
||||
}
|
||||
heightMap.setSize(size);
|
||||
heightMap.perform(editSession, mask, position, size, rotation, yscale, true, false);
|
||||
HeightMap map = getHeightMap();
|
||||
map.setSize(size);
|
||||
map.perform(editSession, mask, position, size, rotation, yscale, true, false);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
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.RadiusMask;
|
||||
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.function.RegionFunction;
|
||||
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.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
@ -35,21 +38,23 @@ public class StencilBrush extends HeightBrush {
|
||||
|
||||
int maxY = editSession.getMaxY();
|
||||
double scale = (yscale / sizeDouble) * (maxY + 1);
|
||||
heightMap.setSize(size);
|
||||
final HeightMap map = getHeightMap();
|
||||
map.setSize(size);
|
||||
int cutoff = onlyWhite ? maxY : 0;
|
||||
|
||||
final AdjacentAnyMask adjacent = new AdjacentAnyMask(editSession, Arrays.asList(new BaseBlock(0)));
|
||||
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);
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(new Mask() {
|
||||
@Override
|
||||
public boolean test(Vector 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);
|
||||
if (dir != null) {
|
||||
int dx = vector.getBlockX() - cx;
|
||||
int dy = vector.getBlockY() - cy;
|
||||
int dz = vector.getBlockZ() - cz;
|
||||
if (dy != 0) {
|
||||
if (dir.getBlockX() != 0) {
|
||||
dx += dir.getBlockX() * dy;
|
||||
@ -57,7 +62,7 @@ public class StencilBrush extends HeightBrush {
|
||||
dz += dir.getBlockZ() * dy;
|
||||
}
|
||||
}
|
||||
double raise = heightMap.getHeight(dx, dz);
|
||||
double raise = map.getHeight(dx, dz);
|
||||
int val = (int) Math.ceil(raise * scale);
|
||||
if (val <= cutoff) {
|
||||
return true;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -1,22 +1,11 @@
|
||||
package com.boydti.fawe.object.brush.heightmap;
|
||||
|
||||
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.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
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.Raster;
|
||||
import java.io.IOException;
|
||||
@ -24,7 +13,7 @@ import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class ScalableHeightMap {
|
||||
public class ScalableHeightMap implements com.boydti.fawe.object.brush.heightmap.HeightMap{
|
||||
public int size2;
|
||||
public int size;
|
||||
|
||||
@ -41,11 +30,13 @@ public class ScalableHeightMap {
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
this.size2 = size * size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHeight(int x, int z) {
|
||||
int dx = Math.abs(x);
|
||||
int dz = Math.abs(z);
|
||||
@ -117,115 +108,4 @@ public class ScalableHeightMap {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -1453,7 +1453,65 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
||||
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(
|
||||
(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
|
||||
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
|
||||
|
@ -542,18 +542,22 @@ public class BrushCommands {
|
||||
max = -1
|
||||
)
|
||||
@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);
|
||||
BrushTool tool = session.getBrushTool(player);
|
||||
InputStream stream = getHeightmapStream(filename);
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
HeightBrush brush;
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
|
||||
@ -695,8 +699,8 @@ public class BrushCommands {
|
||||
max = 4
|
||||
)
|
||||
@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 {
|
||||
terrainBrush(player, session, radius, filename, rotation, yscale, false, ScalableHeightMap.Shape.CONE);
|
||||
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, randomRotate, ScalableHeightMap.Shape.CONE);
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -710,8 +714,8 @@ public class BrushCommands {
|
||||
max = 4
|
||||
)
|
||||
@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 {
|
||||
terrainBrush(player, session, radius, filename, rotation, yscale, true, ScalableHeightMap.Shape.CYLINDER);
|
||||
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, randomRotate, ScalableHeightMap.Shape.CYLINDER);
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -725,8 +729,8 @@ public class BrushCommands {
|
||||
max = 4
|
||||
)
|
||||
@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 {
|
||||
terrainBrush(player, session, radius, filename, rotation, yscale, true, ScalableHeightMap.Shape.CONE);
|
||||
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, randomRotate, ScalableHeightMap.Shape.CONE);
|
||||
}
|
||||
|
||||
private InputStream getHeightmapStream(String filename) {
|
||||
@ -760,24 +764,29 @@ public class BrushCommands {
|
||||
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);
|
||||
InputStream stream = getHeightmapStream(filename);
|
||||
BrushTool tool = session.getBrushTool(player);
|
||||
tool.setSize(radius);
|
||||
HeightBrush brush;
|
||||
if (flat) {
|
||||
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) {
|
||||
tool.setBrush(new FlattenBrush(stream, rotation, yscale, null, shape), "worldedit.brush.height", player);
|
||||
brush = new FlattenBrush(stream, rotation, yscale, null, shape);
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user