Better angle mask + some command tweaks

This commit is contained in:
Jesse Boyd 2017-03-10 14:25:09 +11:00
parent 177e2252cc
commit 0434755333
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
5 changed files with 43 additions and 100 deletions

View File

@ -1,112 +1,55 @@
package com.boydti.fawe.object.mask;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.function.mask.Mask2D;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import java.util.HashMap;
import javax.annotation.Nullable;
public class AngleMask extends SolidBlockMask implements ResettableMask {
private final int max;
private final int min;
public class AngleMask extends SolidBlockMask {
private static double ADJACENT_MOD = 0.5;
private static double DIAGONAL_MOD = 1 / Math.sqrt(8);
private final double max;
private final double min;
private final EditSession extent;
private MutableBlockVector mutable = new MutableBlockVector();
private int maxY;
public AngleMask(Extent extent, int min, int max) {
super(extent);
this.maxY = extent.getMaximumPoint().getBlockY();
public AngleMask(EditSession editSession, double min, double max) {
super(editSession);
this.extent = editSession;
this.min = min;
this.max = max;
this.maxY = extent.getMaxY();
}
private HashMap<Long, Integer> heights = new HashMap<>();
private long tick = 0;
@Override
public boolean test(Vector vector) {
return testAngle(vector) && getExtent().getLazyBlock(vector).getId() != 0;
}
private boolean testAngle(Vector vector) {
long currentTick = Fawe.get().getTimer().getTick();
if (tick != (tick = currentTick)) {
heights.clear();
tick = currentTick;
}
return getAngle(vector);
}
@Override
public void reset() {
this.heights.clear();
}
public boolean getAngle(Vector vector) {
int x = vector.getBlockX();
int z = vector.getBlockZ();
// int o = getHighestTerrainBlock(x, z, 0, maxY);
int y = vector.getBlockY();
if (getHighestTerrainBlock(x - 1, z, y + min, y + max) != -1) {
int z = vector.getBlockZ();
BaseBlock block = extent.getBlock(x, y, z);
if (!test(block.getId(), block.getData())) {
return false;
}
block = extent.getBlock(x, y + 1, z);
if (test(block.getId(), block.getData())) {
return false;
}
double slope;
boolean aboveMin;
slope = Math.abs(extent.getNearestSurfaceTerrainBlock(x + 1, z, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x - 1, z, y, 0, maxY)) * ADJACENT_MOD;
if (slope >= min && max >= Math.max(maxY - y, y)) {
return true;
}
if (getHighestTerrainBlock(x + 1, z, y + min, y + max) != -1) {
return true;
}
if (getHighestTerrainBlock(x, z - 1, y + min, y + max) != -1) {
return true;
}
if (getHighestTerrainBlock(x, z + 1, y + min, y + max) != -1) {
return true;
}
return false;
}
private MutableBlockVector mutable = new MutableBlockVector();
private int getHighestTerrainBlock(final int x, final int z, int minY, int maxY) {
long pair = MathMan.pairInt(x, z);
Integer height = heights.get(pair);
if (height != null) {
if (height >= minY && height <= maxY && height >= 0 && height <= this.maxY) {
return height;
} else {
return -1;
}
}
int maxSearchY = Math.min(this.maxY, Math.max(0, maxY));
int minSearchY = Math.min(this.maxY, Math.max(0, minY));
mutable.mutX(x);
mutable.mutZ(z);
boolean air = false;
if (maxSearchY != this.maxY) {
mutable.mutY(maxSearchY + 1);
air = !super.test(mutable);
}
for (int y = maxSearchY; y >= minSearchY; --y) {
mutable.mutY(y);
if (super.test(mutable)) {
if (!air) {
break;
}
heights.put(pair, y);
return y;
} else {
air = true;
}
}
if (minSearchY == 0 && maxSearchY == this.maxY) {
heights.put(pair, -1);
} else {
int value = getHighestTerrainBlock(x, z, 0, this.maxY);
heights.put(pair, value);
}
return -1;
slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x, z - 1, y, 0, maxY)) * ADJACENT_MOD);
slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x + 1, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x - 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD);
slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x - 1, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x + 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD);
return (slope >= min && slope <= max);
}
@Nullable

View File

@ -132,7 +132,7 @@ public class ClipboardCommands {
@Command(
aliases = { "/copy" },
aliases = { "/copy", "/c" },
flags = "em",
desc = "Copy the selection to the clipboard",
help = "Copy the selection to the clipboard\n" +
@ -350,7 +350,7 @@ public class ClipboardCommands {
}
@Command(
aliases = { "/paste" },
aliases = { "/paste", "/p" },
usage = "",
flags = "sao",
desc = "Paste the clipboard's contents",

View File

@ -290,7 +290,7 @@ public class RegionCommands {
}
@Command(
aliases = { "/replace", "/re", "/rep" },
aliases = { "/replace", "/re", "/rep", "/r" },
usage = "[from-block] <to-block>",
desc = "Replace all blocks in the selection with another",
flags = "f",

View File

@ -81,7 +81,7 @@ public class SelectionCommands {
}
@Command(
aliases = { "/pos1", "posa" },
aliases = { "/pos1", "posa", "/1" },
usage = "[coordinates]",
desc = "Set position 1",
min = 0,
@ -113,7 +113,7 @@ public class SelectionCommands {
}
@Command(
aliases = { "/pos2", "posb" },
aliases = { "/pos2", "posb", "/2" },
usage = "[coordinates]",
desc = "Set position 2",
min = 0,

View File

@ -252,17 +252,17 @@ public class DefaultMaskParser extends FaweParser<Mask> {
throw new SuggestInputParseException(input, "/<min-angle>:<max-angle>");
}
try {
int y1,y2;
double y1,y2;
if (split[0].endsWith("d")) {
double y1d = Expression.compile(split[0].substring(0, split[0].length() - 1)).evaluate();
double y2d = Expression.compile(split[1].substring(0, split[1].length() - 1)).evaluate();
y1 = (int) Math.round(Math.tan(y1d * (Math.PI / 180)));
y2 = (int) Math.round(Math.tan(y2d * (Math.PI / 180)));
y1 = (Math.tan(y1d * (Math.PI / 180)));
y2 = (Math.tan(y2d * (Math.PI / 180)));
} else {
y1 = (int) (Expression.compile(split[0]).evaluate());
y2 = (int) (Expression.compile(split[1]).evaluate());
y1 = (Expression.compile(split[0]).evaluate());
y2 = (Expression.compile(split[1]).evaluate());
}
return new AngleMask(extent, y1, y2);
return new AngleMask(Request.request().getEditSession(), y1, y2);
} catch (NumberFormatException | ExpressionException e) {
throw new SuggestInputParseException(input, "/<min-angle>:<max-angle>");
}