Create SurfaceAngleMask (#1215)

This commit is contained in:
Joseph Thomas 2021-08-08 11:59:42 +02:00 committed by GitHub
parent 2376ce8d9d
commit d10b038e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 148 additions and 0 deletions

View File

@ -0,0 +1,45 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.function.mask.SurfaceAngleMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class SurfaceAngleMaskParser extends RichParser<Mask> {
/**
* Create a new surface angle mask parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public SurfaceAngleMaskParser(WorldEdit worldEdit) {
super(worldEdit, "#surfaceangle");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index <= 2) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
return Stream.empty();
}
public Mask parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length > 3) {
return null;
}
double min = Double.parseDouble(arguments[0]);
double max = Double.parseDouble(arguments[1]);
int size = (arguments.length > 2 ? Integer.parseInt(arguments[2]) : 1);
return new SurfaceAngleMask(context.getExtent(), min, max, size);
}
}

View File

@ -0,0 +1,101 @@
package com.fastasyncworldedit.core.function.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;
import com.sk89q.worldedit.math.Vector3;
import java.util.ArrayList;
public class SurfaceAngleMask extends AbstractExtentMask {
private final double min;
private final double max;
private final int size;
public SurfaceAngleMask(Extent extent, double min, double max, int size) {
super(extent);
this.min = min;
this.max = max;
this.size = size;
}
@Override
public boolean test(BlockVector3 vector) {
if (!vector.getBlock(getExtent()).isAir() && nextToAir(vector)) {
double angle = 1 - getAverageAirDirection(vector.toVector3(), size).getY();
return (angle >= (min / 90.0) && angle <= (max / 90.0));
}
return false;
}
@Override
public boolean test(Extent extent, BlockVector3 vector) {
if (!vector.getBlock(getExtent()).isAir() && nextToAir(vector)) {
double angle = 1 - getAverageAirDirection(vector.toVector3(), size).getY();
return (angle >= (min / 90.0) && angle <= (max / 90.0));
}
return false;
}
private Vector3 getAverageAirDirection(Vector3 currentLocation, int size) {
ArrayList<Vector3> airDirections = new ArrayList<>();
for (int i = -size; i <= size; i++) {
for (int j = -size; j <= size; j++) {
for (int k = -size; k <= size; k++) {
Vector3 block = Vector3.at(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ()).add(
0.5,
0.5,
0.5
).add(i, j, k);
if (block
.toBlockPoint()
.clampY(getExtent().getMinY(), getExtent().getMaxY())
.getBlock(getExtent())
.getMaterial()
.isAir()) {
airDirections.add(block.subtract(currentLocation.add(0.5, 0.5, 0.5)));
}
}
}
}
double x = 0.0;
double y = 0.0;
double z = 0.0;
for (Vector3 vector3 : airDirections) {
x += vector3.getX();
y += vector3.getY();
z += vector3.getZ();
}
Vector3 averageAirDirection = Vector3.at(x / airDirections.size(), y / airDirections.size(), z / airDirections.size());
return (Double.isNaN(averageAirDirection.getY()) ? Vector3.ZERO : averageAirDirection.normalize());
}
@Override
public Mask copy() {
return new SurfaceAngleMask(super.getExtent(), min, max, size);
}
private boolean nextToAir(BlockVector3 blockVector3) {
if (getExtent().getBlock(blockVector3.add(1, 0, 0)).toBaseBlock().getMaterial().isAir()) {
return true;
}
if (getExtent().getBlock(blockVector3.add(-1, 0, 0)).toBaseBlock().getMaterial().isAir()) {
return true;
}
if (getExtent().getBlock(blockVector3.add(0, 1, 0)).toBaseBlock().getMaterial().isAir()) {
return true;
}
if (getExtent().getBlock(blockVector3.add(0, -1, 0)).toBaseBlock().getMaterial().isAir()) {
return true;
}
if (getExtent().getBlock(blockVector3.add(0, 0, 1)).toBaseBlock().getMaterial().isAir()) {
return true;
}
return getExtent().getBlock(blockVector3.add(0, 0, -1)).toBaseBlock().getMaterial().isAir();
}
}

View File

@ -28,6 +28,7 @@ import com.fastasyncworldedit.core.extension.factory.parser.mask.LiquidMaskParse
import com.fastasyncworldedit.core.extension.factory.parser.mask.ROCAngleMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.ROCAngleMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.RichOffsetMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.RichOffsetMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.SimplexMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.SimplexMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.SurfaceAngleMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.SurfaceMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.SurfaceMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.TrueMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.TrueMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.WallMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.WallMaskParser;
@ -108,6 +109,7 @@ public final class MaskFactory extends AbstractFactory<Mask> {
register(new XAxisMaskParser(worldEdit)); register(new XAxisMaskParser(worldEdit));
register(new YAxisMaskParser(worldEdit)); register(new YAxisMaskParser(worldEdit));
register(new ZAxisMaskParser(worldEdit)); register(new ZAxisMaskParser(worldEdit));
register(new SurfaceAngleMaskParser(worldEdit));
//FAWE end //FAWE end
} }