mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-10 06:38:35 +00:00
Allow parallelisation of masks (#636)
* Allow parallelisation of masks Increasing performance improvement with increased masking complexity and edit size. * Address comments - Rename Mask#clone to Mask#copy - Rename Mask2D#copy to Mask2D#copy2D - Correct formatting * cx -> centerX * Make various operations relying on a single SingleThreadQueueExtent instance (mainly brushes) thread safe
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.brush.mask.ImageBrushMask;
|
||||
import com.boydti.fawe.object.collection.SummedColorTable;
|
||||
import com.boydti.fawe.object.mask.SurfaceMask;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
@ -8,18 +9,14 @@ import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
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.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
@ -30,8 +27,8 @@ public class ImageBrush implements Brush {
|
||||
private final SummedColorTable table;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final double centerX;
|
||||
private final double centerZ;
|
||||
private final double centerImageX;
|
||||
private final double centerImageZ;
|
||||
|
||||
private final ColorFunction colorFunction;
|
||||
|
||||
@ -40,8 +37,8 @@ public class ImageBrush implements Brush {
|
||||
this.table = new SummedColorTable(image, alpha);
|
||||
this.width = image.getWidth();
|
||||
this.height = image.getHeight();
|
||||
this.centerX = width / 2d;
|
||||
this.centerZ = height / 2d;
|
||||
this.centerImageX = width / 2d;
|
||||
this.centerImageZ = height / 2d;
|
||||
|
||||
if (alpha) {
|
||||
colorFunction = (x1, z1, x2, z2, extent, pos) -> {
|
||||
@ -65,17 +62,12 @@ public class ImageBrush implements Brush {
|
||||
}
|
||||
}
|
||||
|
||||
private interface ColorFunction {
|
||||
public interface ColorFunction {
|
||||
int call(int x1, int z1, int x2, int z2, Extent extent, BlockVector3 pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
TextureUtil texture = session.getTextureUtil();
|
||||
|
||||
final int cx = position.getBlockX();
|
||||
final int cy = position.getBlockY();
|
||||
final int cz = position.getBlockZ();
|
||||
public void build(EditSession editSession, BlockVector3 center, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
final Mask solid = new SurfaceMask(editSession);
|
||||
|
||||
double scale = Math.max(width, height) / sizeDouble;
|
||||
@ -85,56 +77,11 @@ public class ImageBrush implements Brush {
|
||||
float pitch = loc.getPitch();
|
||||
AffineTransform transform = new AffineTransform().rotateY((-yaw) % 360).rotateX((pitch - 90) % 360).inverse();
|
||||
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(new AbstractExtentMask(editSession) {
|
||||
private final MutableVector3 mutable = new MutableVector3();
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (solid.test(vector)) {
|
||||
int dx = vector.getBlockX() - cx;
|
||||
int dy = vector.getBlockY() - cy;
|
||||
int dz = vector.getBlockZ() - cz;
|
||||
|
||||
Vector3 pos1 = transform.apply(mutable.setComponents(dx - 0.5, dy - 0.5, dz - 0.5));
|
||||
int x1 = (int) (pos1.getX() * scale + centerX);
|
||||
int z1 = (int) (pos1.getZ() * scale + centerZ);
|
||||
|
||||
Vector3 pos2 = transform.apply(mutable.setComponents(dx + 0.5, dy + 0.5, dz + 0.5));
|
||||
int x2 = (int) (pos2.getX() * scale + centerX);
|
||||
int z2 = (int) (pos2.getZ() * scale + centerZ);
|
||||
if (x2 < x1) {
|
||||
int tmp = x1;
|
||||
x1 = x2;
|
||||
x2 = tmp;
|
||||
}
|
||||
if (z2 < z1) {
|
||||
int tmp = z1;
|
||||
z1 = z2;
|
||||
z2 = tmp;
|
||||
}
|
||||
|
||||
if (x1 >= width || x2 < 0 || z1 >= height || z2 < 0) return false;
|
||||
|
||||
|
||||
int color = colorFunction.call(x1, z1, x2, z2, editSession, vector);
|
||||
if (color != 0) {
|
||||
BlockType block = texture.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
editSession.setBlock(vector, block.getDefaultState());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, vector -> true, Integer.MAX_VALUE);
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(
|
||||
new ImageBrushMask(solid, center, transform, scale, centerImageX, centerImageZ, width, height, colorFunction, editSession,
|
||||
session.getTextureUtil()), vector -> true, Integer.MAX_VALUE);
|
||||
visitor.setDirections(Arrays.asList(visitor.DIAGONAL_DIRECTIONS));
|
||||
visitor.visit(position);
|
||||
visitor.visit(center);
|
||||
Operations.completeBlindly(visitor);
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,20 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.brush.mask.LayerBrushMask;
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.boydti.fawe.object.mask.AdjacentAnyMask;
|
||||
import com.boydti.fawe.object.mask.RadiusMask;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.MaskIntersection;
|
||||
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.BreadthFirstSearch;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
@ -26,7 +24,6 @@ public class LayerBrush implements Brush {
|
||||
|
||||
private final BlockState[] layers;
|
||||
private RecursiveVisitor visitor;
|
||||
private MutableBlockVector3 mutable = new MutableBlockVector3();
|
||||
|
||||
public LayerBrush(BlockState[] layers) {
|
||||
this.layers = layers;
|
||||
@ -37,48 +34,12 @@ public class LayerBrush implements Brush {
|
||||
final AdjacentAnyMask adjacent = new AdjacentAnyMask(new BlockMask(editSession).add(BlockTypes.AIR, BlockTypes.CAVE_AIR, BlockTypes.VOID_AIR));
|
||||
final SolidBlockMask solid = new SolidBlockMask(editSession);
|
||||
final RadiusMask radius = new RadiusMask(0, (int) size);
|
||||
visitor = new RecursiveVisitor(new Mask() {
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
return solid.test(vector) && radius.test(vector) && adjacent.test(vector);
|
||||
}
|
||||
}, function -> true);
|
||||
visitor = new RecursiveVisitor(new MaskIntersection(adjacent, solid, radius), function -> true);
|
||||
visitor.visit(position);
|
||||
visitor.setDirections(Arrays.asList(BreadthFirstSearch.DIAGONAL_DIRECTIONS));
|
||||
Operations.completeBlindly(visitor);
|
||||
BlockVectorSet visited = visitor.getVisited();
|
||||
visitor = new RecursiveVisitor(new AbstractExtentMask(editSession) {
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 pos) {
|
||||
int depth = visitor.getDepth() + 1;
|
||||
if (depth > 1) {
|
||||
boolean found = false;
|
||||
BlockState previous = layers[depth - 1];
|
||||
BlockState previous2 = layers[depth - 2];
|
||||
for (BlockVector3 dir : BreadthFirstSearch.DEFAULT_DIRECTIONS) {
|
||||
mutable.setComponents(pos.getBlockX() + dir.getBlockX(), pos.getBlockY() + dir.getBlockY(), pos.getBlockZ() + dir.getBlockZ());
|
||||
if (visitor.isVisited(mutable) && editSession.getBlock(mutable.getBlockX(), mutable.getBlockY(), mutable.getBlockZ()) == previous) {
|
||||
mutable.setComponents(pos.getBlockX() + dir.getBlockX() * 2, pos.getBlockY() + dir.getBlockY() * 2, pos.getBlockZ() + dir.getBlockZ() * 2);
|
||||
if (visitor.isVisited(mutable) && editSession.getBlock(mutable.getBlockX(), mutable.getBlockY(), mutable.getBlockZ()) == previous2) {
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !adjacent.test(pos);
|
||||
}
|
||||
}, pos -> {
|
||||
visitor = new RecursiveVisitor(new LayerBrushMask(editSession, visitor, layers, adjacent), pos -> {
|
||||
int depth = visitor.getDepth();
|
||||
BlockState currentPattern = layers[depth];
|
||||
return currentPattern.apply(editSession, pos, pos);
|
||||
|
@ -1,11 +1,10 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.brush.mask.SplatterBrushMask;
|
||||
import com.boydti.fawe.object.collection.LocalBlockVectorSet;
|
||||
import com.boydti.fawe.object.mask.SurfaceMask;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
|
||||
@ -13,7 +12,6 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class SplatterBrush extends ScatterBrush {
|
||||
private final boolean solid;
|
||||
@ -36,23 +34,8 @@ public class SplatterBrush extends ScatterBrush {
|
||||
final int size2 = (int) (size * size);
|
||||
SurfaceMask surface = new SurfaceMask(editSession);
|
||||
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(new AbstractExtentMask(editSession) {
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
double dist = vector.distanceSq(position);
|
||||
if (dist < size2 && !placed.contains(vector) && ThreadLocalRandom.current().nextInt(5) < 2
|
||||
&& surface.test(vector)) {
|
||||
placed.add(vector);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, vector -> editSession.setBlock(vector, finalPattern), recursion);
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(new SplatterBrushMask(editSession, position, size2, surface, placed),
|
||||
vector -> editSession.setBlock(vector, finalPattern), recursion);
|
||||
visitor.setMaxBranch(2);
|
||||
visitor.setDirections(Arrays.asList(BreadthFirstSearch.DIAGONAL_DIRECTIONS));
|
||||
visitor.visit(position);
|
||||
|
@ -1,26 +1,21 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.brush.heightmap.HeightMap;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.object.brush.mask.StencilBrushMask;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
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.BreadthFirstSearch;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class StencilBrush extends HeightBrush {
|
||||
private final boolean onlyWhite;
|
||||
@ -31,10 +26,7 @@ public class StencilBrush extends HeightBrush {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
final int cx = position.getBlockX();
|
||||
final int cy = position.getBlockY();
|
||||
final int cz = position.getBlockZ();
|
||||
public void build(EditSession editSession, BlockVector3 center, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
int size = (int) sizeDouble;
|
||||
int size2 = (int) (sizeDouble * sizeDouble);
|
||||
int maxY = editSession.getMaxY();
|
||||
@ -55,42 +47,11 @@ public class StencilBrush extends HeightBrush {
|
||||
AffineTransform transform = new AffineTransform().rotateY((-yaw) % 360).rotateX(pitch - 90).inverse();
|
||||
|
||||
double scale = (yscale / sizeDouble) * (maxY + 1);
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(new AbstractExtentMask(editSession) {
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
private final MutableVector3 mutable = new MutableVector3();
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (solid.test(vector)) {
|
||||
int dx = vector.getBlockX() - cx;
|
||||
int dy = vector.getBlockY() - cy;
|
||||
int dz = vector.getBlockZ() - cz;
|
||||
|
||||
Vector3 srcPos = transform.apply(mutable.setComponents(dx, dy, dz));
|
||||
dx = MathMan.roundInt(srcPos.getX());
|
||||
dz = MathMan.roundInt(srcPos.getZ());
|
||||
|
||||
int distance = dx * dx + dz * dz;
|
||||
if (distance > size2 || Math.abs(dx) > 256 || Math.abs(dz) > 256) return false;
|
||||
|
||||
double raise = map.getHeight(dx, dz);
|
||||
int val = (int) Math.ceil(raise * scale) + add;
|
||||
if (val < cutoff) {
|
||||
return true;
|
||||
}
|
||||
if (val >= 255 || ThreadLocalRandom.current().nextInt(maxY) < val) {
|
||||
editSession.setBlock(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), pattern);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, vector -> true, Integer.MAX_VALUE);
|
||||
RecursiveVisitor visitor =
|
||||
new RecursiveVisitor(new StencilBrushMask(editSession, solid, center, transform, size2, map, scale, add, cutoff, maxY, pattern),
|
||||
vector -> true, Integer.MAX_VALUE);
|
||||
visitor.setDirections(Arrays.asList(BreadthFirstSearch.DIAGONAL_DIRECTIONS));
|
||||
visitor.visit(position);
|
||||
visitor.visit(center);
|
||||
Operations.completeBlindly(visitor);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,107 @@
|
||||
package com.boydti.fawe.object.brush.mask;
|
||||
|
||||
import com.boydti.fawe.object.brush.ImageBrush;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
|
||||
public class ImageBrushMask extends AbstractExtentMask {
|
||||
|
||||
private final MutableVector3 mutable = new MutableVector3();
|
||||
private final Mask solid;
|
||||
private final BlockVector3 center;
|
||||
private final Transform transform;
|
||||
private final double scale;
|
||||
private final double centerImageX;
|
||||
private final double centerImageZ;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final ImageBrush.ColorFunction colorFunction;
|
||||
private final EditSession session;
|
||||
private final TextureUtil texture;
|
||||
|
||||
public ImageBrushMask(Mask solid,
|
||||
BlockVector3 center,
|
||||
Transform transform,
|
||||
double scale,
|
||||
double centerImageX,
|
||||
double centerImageZ,
|
||||
int width,
|
||||
int height,
|
||||
ImageBrush.ColorFunction colorFunction,
|
||||
EditSession session,
|
||||
TextureUtil texture) {
|
||||
super(session);
|
||||
this.solid = solid;
|
||||
this.center = center;
|
||||
this.transform = transform;
|
||||
this.scale = scale;
|
||||
this.centerImageX = centerImageX;
|
||||
this.centerImageZ = centerImageZ;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.colorFunction = colorFunction;
|
||||
this.session = session;
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (solid.test(vector)) {
|
||||
int dx = vector.getBlockX() - center.getBlockX();
|
||||
int dy = vector.getBlockY() - center.getBlockY();
|
||||
int dz = vector.getBlockZ() - center.getBlockZ();
|
||||
|
||||
Vector3 pos1 = transform.apply(mutable.setComponents(dx - 0.5, dy - 0.5, dz - 0.5));
|
||||
int x1 = (int) (pos1.getX() * scale + centerImageX);
|
||||
int z1 = (int) (pos1.getZ() * scale + centerImageZ);
|
||||
|
||||
Vector3 pos2 = transform.apply(mutable.setComponents(dx + 0.5, dy + 0.5, dz + 0.5));
|
||||
int x2 = (int) (pos2.getX() * scale + centerImageX);
|
||||
int z2 = (int) (pos2.getZ() * scale + centerImageZ);
|
||||
if (x2 < x1) {
|
||||
int tmp = x1;
|
||||
x1 = x2;
|
||||
x2 = tmp;
|
||||
}
|
||||
if (z2 < z1) {
|
||||
int tmp = z1;
|
||||
z1 = z2;
|
||||
z2 = tmp;
|
||||
}
|
||||
|
||||
if (x1 >= width || x2 < 0 || z1 >= height || z2 < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int color = colorFunction.call(x1, z1, x2, z2, session, vector);
|
||||
if (color != 0) {
|
||||
BlockType block = texture.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
session.setBlock(vector, block.getDefaultState());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new ImageBrushMask(solid.copy(), center.toImmutable(), transform, scale, centerImageX, centerImageZ, width, height, colorFunction,
|
||||
session, texture);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.boydti.fawe.object.brush.mask;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
|
||||
public class LayerBrushMask extends AbstractExtentMask {
|
||||
|
||||
private final EditSession editSession;
|
||||
private final RecursiveVisitor visitor;
|
||||
private final BlockState[] layers;
|
||||
private final MutableBlockVector3 mutable = new MutableBlockVector3();
|
||||
private final Mask adjacent;
|
||||
|
||||
public LayerBrushMask(EditSession editSession, RecursiveVisitor visitor, BlockState[] layers, Mask adjacent) {
|
||||
super(editSession);
|
||||
this.editSession = editSession;
|
||||
this.visitor = visitor;
|
||||
this.layers = layers;
|
||||
this.adjacent = adjacent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 pos) {
|
||||
int depth = visitor.getDepth() + 1;
|
||||
if (depth > 1) {
|
||||
boolean found = false;
|
||||
BlockState previous = layers[depth - 1];
|
||||
BlockState previous2 = layers[depth - 2];
|
||||
for (BlockVector3 dir : BreadthFirstSearch.DEFAULT_DIRECTIONS) {
|
||||
mutable.setComponents(pos.getBlockX() + dir.getBlockX(), pos.getBlockY() + dir.getBlockY(), pos.getBlockZ() + dir.getBlockZ());
|
||||
if (visitor.isVisited(mutable) && editSession.getBlock(mutable.getBlockX(), mutable.getBlockY(), mutable.getBlockZ()) == previous) {
|
||||
mutable.setComponents(pos.getBlockX() + dir.getBlockX() * 2, pos.getBlockY() + dir.getBlockY() * 2,
|
||||
pos.getBlockZ() + dir.getBlockZ() * 2);
|
||||
if (visitor.isVisited(mutable)
|
||||
&& editSession.getBlock(mutable.getBlockX(), mutable.getBlockY(), mutable.getBlockZ()) == previous2) {
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !adjacent.test(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new LayerBrushMask(editSession, visitor, layers.clone(), adjacent.copy());
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.boydti.fawe.object.brush.mask;
|
||||
|
||||
import com.boydti.fawe.object.collection.LocalBlockVectorSet;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class SplatterBrushMask extends AbstractExtentMask {
|
||||
|
||||
private final BlockVector3 position;
|
||||
private final int size2;
|
||||
private final Mask surface;
|
||||
private final LocalBlockVectorSet placed;
|
||||
|
||||
public SplatterBrushMask(EditSession editSession, BlockVector3 position, int size2, Mask surface, LocalBlockVectorSet placed) {
|
||||
super(editSession);
|
||||
this.position = position;
|
||||
this.size2 = size2;
|
||||
this.surface = surface;
|
||||
this.placed = placed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
double dist = vector.distanceSq(position);
|
||||
synchronized (placed) {
|
||||
if (dist < size2 && !placed.contains(vector) && ThreadLocalRandom.current().nextInt(5) < 2 && surface.test(vector)) {
|
||||
placed.add(vector);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
// There should not be multiple instances to be thread safe
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.boydti.fawe.object.brush.mask;
|
||||
|
||||
import com.boydti.fawe.object.brush.heightmap.HeightMap;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class StencilBrushMask extends AbstractExtentMask {
|
||||
|
||||
private final MutableVector3 mutable = new MutableVector3();
|
||||
private final EditSession editSession;
|
||||
private final Mask solid;
|
||||
private final BlockVector3 center;
|
||||
private final Transform transform;
|
||||
private final int size2;
|
||||
private final HeightMap map;
|
||||
private final double scale;
|
||||
private final int add;
|
||||
private final int cutoff;
|
||||
private final int maxY;
|
||||
private final Pattern pattern;
|
||||
|
||||
public StencilBrushMask(EditSession editSession,
|
||||
Mask solid,
|
||||
BlockVector3 center,
|
||||
Transform transform,
|
||||
int size2,
|
||||
HeightMap map,
|
||||
double scale,
|
||||
int add,
|
||||
int cutoff,
|
||||
int maxY,
|
||||
Pattern pattern) {
|
||||
super(editSession);
|
||||
this.editSession = editSession;
|
||||
this.solid = solid;
|
||||
this.center = center;
|
||||
this.transform = transform;
|
||||
this.size2 = size2;
|
||||
this.map = map;
|
||||
this.scale = scale;
|
||||
this.add = add;
|
||||
this.cutoff = cutoff;
|
||||
this.maxY = maxY;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Extent extent, BlockVector3 vector) {
|
||||
return test(vector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (solid.test(vector)) {
|
||||
int dx = vector.getBlockX() - center.getBlockX();
|
||||
int dy = vector.getBlockY() - center.getBlockY();
|
||||
int dz = vector.getBlockZ() - center.getBlockZ();
|
||||
|
||||
Vector3 srcPos = transform.apply(mutable.setComponents(dx, dy, dz));
|
||||
dx = MathMan.roundInt(srcPos.getX());
|
||||
dz = MathMan.roundInt(srcPos.getZ());
|
||||
|
||||
int distance = dx * dx + dz * dz;
|
||||
if (distance > size2 || Math.abs(dx) > 256 || Math.abs(dz) > 256) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double raise = map.getHeight(dx, dz);
|
||||
int val = (int) Math.ceil(raise * scale) + add;
|
||||
if (val < cutoff) {
|
||||
return true;
|
||||
}
|
||||
if (val >= 255 || ThreadLocalRandom.current().nextInt(maxY) < val) {
|
||||
editSession.setBlock(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), pattern);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new StencilBrushMask(editSession, solid.copy(), center.toImmutable(), transform, size2, map, scale, add, cutoff, maxY, pattern);
|
||||
}
|
||||
}
|
@ -30,4 +30,9 @@ public class AbstractDelegateMask extends AbstractMask {
|
||||
return mask.toMask2D();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new AbstractDelegateMask(mask.copy());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -53,4 +52,9 @@ public class AdjacentAnyMask extends AbstractMask implements ResettableMask {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new AdjacentAnyMask(mask.copy());
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ public class AdjacentMask extends AbstractMask {
|
||||
private final int min;
|
||||
private final int max;
|
||||
private final Mask mask;
|
||||
private MutableBlockVector3 vector;
|
||||
private final MutableBlockVector3 vector;
|
||||
|
||||
public AdjacentMask(Mask mask, int requiredMin, int requiredMax) {
|
||||
this.mask = mask;
|
||||
@ -60,4 +60,9 @@ public class AdjacentMask extends AbstractMask {
|
||||
vector.mutZ(z);
|
||||
return count >= min && count <= max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new AdjacentMask(mask.copy(), min, max);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
|
||||
public class AirMask extends BlockMask {
|
||||
|
||||
public AirMask(Extent extent) {
|
||||
super(extent);
|
||||
add(state -> state.getMaterial().isAir());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new AirMask(getExtent());
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.SolidBlockMask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
@ -44,7 +45,6 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
|
||||
}
|
||||
}
|
||||
|
||||
protected transient int cacheCenX;
|
||||
protected transient int cacheCenZ;
|
||||
protected transient int cacheBotX = Integer.MIN_VALUE;
|
||||
protected transient int cacheBotZ = Integer.MIN_VALUE;
|
||||
@ -173,4 +173,9 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
|
||||
return testSlope(getExtent(), x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new AngleMask(getExtent(), min, max, overlay, distance);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -65,4 +65,9 @@ public class CachedMask extends AbstractDelegateMask implements ResettableMask {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new CachedMask(getMask().copy());
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class DataMask extends AbstractExtentMask implements ResettableMask {
|
||||
@ -37,4 +38,9 @@ public class DataMask extends AbstractExtentMask implements ResettableMask {
|
||||
this.data = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new DataMask(getExtent());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
|
||||
public class ExtremaMask extends AngleMask {
|
||||
public ExtremaMask(Extent extent, double min, double max, boolean overlay, int distance) {
|
||||
@ -62,4 +63,9 @@ public class ExtremaMask extends AngleMask {
|
||||
}
|
||||
return (lastHeight1 - base) + (lastHeight2 - base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new ExtremaMask(getExtent(), min, max, overlay, distance);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class IdDataMask extends AbstractExtentMask implements ResettableMask {
|
||||
@ -31,4 +32,9 @@ public class IdDataMask extends AbstractExtentMask implements ResettableMask {
|
||||
this.combined = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new IdDataMask(getExtent());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class IdMask extends AbstractExtentMask implements ResettableMask {
|
||||
@ -32,4 +33,9 @@ public class IdMask extends AbstractExtentMask implements ResettableMask {
|
||||
this.id = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new IdMask(getExtent());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
|
||||
public class LiquidMask extends BlockMask {
|
||||
|
||||
public LiquidMask(Extent extent) {
|
||||
super(extent);
|
||||
add(state -> state.getMaterial().isLiquid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new LiquidMask(getExtent());
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class PlaneMask extends AbstractMask implements ResettableMask {
|
||||
@ -55,4 +56,9 @@ public class PlaneMask extends AbstractMask implements ResettableMask {
|
||||
mode = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new PlaneMask();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
|
||||
public class ROCAngleMask extends AngleMask {
|
||||
|
||||
@ -31,4 +32,9 @@ public class ROCAngleMask extends AngleMask {
|
||||
|
||||
return lastValue = slope >= min && slope <= max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new ROCAngleMask(getExtent(), min, max, overlay, distance);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class RadiusMask extends AbstractMask implements ResettableMask {
|
||||
@ -13,6 +14,11 @@ public class RadiusMask extends AbstractMask implements ResettableMask {
|
||||
this.maxSqr = max * max;
|
||||
}
|
||||
|
||||
private RadiusMask(Integer minSqr, Integer maxSqr) {
|
||||
this.minSqr = minSqr;
|
||||
this.maxSqr = maxSqr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
pos = null;
|
||||
@ -41,4 +47,9 @@ public class RadiusMask extends AbstractMask implements ResettableMask {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new RadiusMask(minSqr, maxSqr);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
@ -23,4 +24,9 @@ public class RandomMask extends AbstractMask implements ResettableMask {
|
||||
public void reset() {
|
||||
random = new SplittableRandom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new RandomMask(threshold);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.boydti.fawe.object.random.SimplexNoise;
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class SimplexMask extends AbstractMask {
|
||||
@ -18,4 +19,10 @@ public class SimplexMask extends AbstractMask {
|
||||
double value = SimplexNoise.noise(vector.getBlockX() * scale, vector.getBlockY() * scale, vector.getBlockZ() * scale);
|
||||
return value >= min && value <= max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
// The mask is not mutable. There is no need to clone it.
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ package com.boydti.fawe.object.mask;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
public class SurfaceMask extends AdjacentAnyMask {
|
||||
|
||||
public SurfaceMask(Extent extent) {
|
||||
super(getMask(extent));
|
||||
}
|
||||
@ -22,4 +24,10 @@ public class SurfaceMask extends AdjacentAnyMask {
|
||||
public boolean test(BlockVector3 v) {
|
||||
return !getParentMask().test(v.getBlockX(), v.getBlockY(), v.getBlockZ()) && super.test(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
// The mask is not mutable. There is no need to clone it.
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -48,4 +48,9 @@ public class WallMask extends AbstractMask {
|
||||
v.mutZ(z);
|
||||
return count >= min && count <= max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new WallMask(mask.copy(), min, max);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class XAxisMask extends AbstractMask implements ResettableMask {
|
||||
|
||||
private transient int layer = -1;
|
||||
|
||||
public XAxisMask(Extent extent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (layer == -1) {
|
||||
layer = vector.getBlockX();
|
||||
}
|
||||
return vector.getBlockX() == layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.layer = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new XAxisMask(null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class YAxisMask extends AbstractMask implements ResettableMask {
|
||||
|
||||
private transient int layer = -1;
|
||||
|
||||
public YAxisMask(Extent extent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (layer == -1) {
|
||||
layer = vector.getBlockY();
|
||||
}
|
||||
return vector.getBlockY() == layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.layer = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new YAxisMask(null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.sk89q.worldedit.function.mask.AbstractMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class ZAxisMask extends AbstractMask implements ResettableMask {
|
||||
|
||||
private transient int layer = -1;
|
||||
|
||||
public ZAxisMask() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (layer == -1) {
|
||||
layer = vector.getBlockZ();
|
||||
}
|
||||
return vector.getBlockZ() == layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.layer = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask copy() {
|
||||
return new ZAxisMask();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user