Some tweaks to fuzzy region select
This commit is contained in:
parent
f16ebf4f77
commit
64d7052d5f
@ -4,7 +4,6 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
import com.boydti.fawe.object.RegionWrapper;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.WEManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
@ -32,6 +31,10 @@ public class ProcessedWEExtent extends FaweRegionExtent {
|
||||
this.extent = (AbstractDelegateExtent) parent;
|
||||
}
|
||||
|
||||
public void setLimit(FaweLimit other) {
|
||||
this.limit.set(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity createEntity(final Location location, final BaseEntity entity) {
|
||||
if (entity == null) {
|
||||
|
@ -1,15 +1,13 @@
|
||||
package com.boydti.fawe.object.regions;
|
||||
|
||||
import com.boydti.fawe.object.visitor.FuzzySearch;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.regions.AbstractRegion;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
@ -41,53 +39,14 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
return mask;
|
||||
}
|
||||
|
||||
private static int pair(int x, int y, int z) {
|
||||
byte b1 = (byte) y;
|
||||
byte b2 = (byte) (x);
|
||||
byte b3 = (byte) (z);
|
||||
int x16 = (x >> 8) & 0x7;
|
||||
int z16 = (z >> 8) & 0x7;
|
||||
byte b4 = MathMan.pair8(x16, z16);
|
||||
return ((b1 & 0xFF)
|
||||
+ ((b2 & 0xFF) << 8)
|
||||
+ ((b3 & 0xFF) << 16)
|
||||
+ ((b4 & 0x7F) << 24))
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArea() {
|
||||
return set.cardinality();
|
||||
}
|
||||
|
||||
public void select(int x, int y, int z) {
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, new RegionFunction() {
|
||||
@Override
|
||||
public boolean apply(Vector position) throws WorldEditException {
|
||||
return true;
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public boolean isVisited(Node node) {
|
||||
return contains(node.getX(), node.getY(), node.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisited(Node node, int depth) {
|
||||
try {
|
||||
set(node.getX(), node.getY(), node.getZ());
|
||||
} catch (RegionOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanVisited(int layer) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
visitor.visit(new Vector(x, y, z));
|
||||
Operations.completeBlindly(visitor);
|
||||
FuzzySearch search = new FuzzySearch(this, extent, new Vector(x, y, z));
|
||||
Operations.completeBlindly(search);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,13 +64,13 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
|
||||
@Override
|
||||
public BlockVector next() {
|
||||
int b1 = ((byte) index) & 0xFF;
|
||||
int b2 = ((byte) (index >> 8)) & 0xFF;
|
||||
int b3 = ((byte)(index >> 16)) & 0xFF;
|
||||
byte b4 = (byte) (index >> 24);
|
||||
pos.x = offsetX + (((b2 + ((MathMan.unpair8x(b4)) << 8)) << 21) >> 21);
|
||||
int b1 = (index & 0xFF);
|
||||
int b2 = ((byte) (index >> 8)) & 0x7F;
|
||||
int b3 = ((byte)(index >> 15)) & 0xFF;
|
||||
int b4 = ((byte) (index >> 23)) & 0xFF;
|
||||
pos.x = offsetX + (((b3 + ((MathMan.unpair8x(b2)) << 8)) << 21) >> 21);
|
||||
pos.y = offsetY + b1;
|
||||
pos.z = offsetZ + (((b3 + ((MathMan.unpair8y(b4)) << 8)) << 21) >> 21);
|
||||
pos.z = offsetZ + (((b4 + ((MathMan.unpair8y(b2)) << 8)) << 21) >> 21);
|
||||
return pos;
|
||||
}
|
||||
|
||||
@ -124,8 +83,8 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
|
||||
public void set(int x, int y, int z) throws RegionOperationException{
|
||||
if (populated) {
|
||||
if (++count > 1048576) {
|
||||
throw new RegionOperationException("Selection is too large! (1048576 blocks)");
|
||||
if (++count > 16777216) {
|
||||
throw new RegionOperationException("Selection is too large! (16777216 blocks)");
|
||||
}
|
||||
x -= offsetX;
|
||||
y -= offsetY;
|
||||
@ -137,7 +96,7 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
z = 0;
|
||||
populated = true;
|
||||
}
|
||||
set.set(pair(x, y, z), true);
|
||||
set.set(MathMan.tripleSearchCoords(x, y, z), true);
|
||||
if (x >= 1024 || x <= -1024 || z >= 1024 || z <= -1024) {
|
||||
throw new RegionOperationException("Selection is too large! (1024 blocks wide)");
|
||||
}
|
||||
@ -163,7 +122,7 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
|
||||
public boolean contains(int x, int y, int z) {
|
||||
try {
|
||||
return set.get(pair(x - offsetX, y - offsetY, z - offsetZ));
|
||||
return set.get(MathMan.tripleSearchCoords(x - offsetX, y - offsetY, z - offsetZ));
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -171,12 +130,12 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
|
||||
@Override
|
||||
public Vector getMinimumPoint() {
|
||||
return new Vector(minX, minY, minZ);
|
||||
return new Vector(minX + offsetX, minY + offsetY, minZ + offsetZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getMaximumPoint() {
|
||||
return new Vector(maxX, maxY, maxZ);
|
||||
return new Vector(maxX + offsetX, maxY + offsetY, maxZ + offsetZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -14,7 +14,6 @@ import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
@ -35,7 +34,7 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
|
||||
.player(FawePlayer.wrap(player))
|
||||
.changeSetNull()
|
||||
.checkMemory(false)
|
||||
.autoQueue(false)
|
||||
.autoQueue(true)
|
||||
.build());
|
||||
this.player = player;
|
||||
this.region = new FuzzyRegion(world, getExtent(), mask);
|
||||
@ -55,7 +54,7 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
|
||||
.player(FawePlayer.wrap(player))
|
||||
.changeSetNull()
|
||||
.checkMemory(false)
|
||||
.autoQueue(false)
|
||||
.autoQueue(true)
|
||||
.build();
|
||||
new ExtentTraverser(this).setNext(extent);
|
||||
this.region.setWorld(world);
|
||||
@ -69,13 +68,10 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
|
||||
|
||||
@Override
|
||||
public boolean selectPrimary(Vector position, SelectorLimits limits) {
|
||||
setWorld(getWorld());
|
||||
new MaskTraverser(getMask()).reset(getExtent());
|
||||
positions.clear();
|
||||
positions.add(position);
|
||||
Extent extent = getExtent();
|
||||
if (extent instanceof EditSession) {
|
||||
((EditSession) extent).resetLimit();
|
||||
}
|
||||
new MaskTraverser(getMask()).reset(extent);
|
||||
this.region = new FuzzyRegion(getWorld(), getExtent(), getMask());
|
||||
this.region.select((int) position.x, (int) position.y, (int) position.z);
|
||||
return true;
|
||||
|
@ -0,0 +1,106 @@
|
||||
package com.boydti.fawe.object.visitor;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.collection.SparseBitSet;
|
||||
import com.boydti.fawe.object.regions.FuzzyRegion;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.RunContext;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import java.util.List;
|
||||
|
||||
public class FuzzySearch implements Operation {
|
||||
|
||||
private final FuzzyRegion region;
|
||||
private final SparseBitSet visited;
|
||||
private final SparseBitSet queue;
|
||||
private final int offsetZ;
|
||||
private final int offsetX;
|
||||
private final Extent extent;
|
||||
private final int maxY;
|
||||
private int affected;
|
||||
|
||||
public FuzzySearch(FuzzyRegion region, Extent extent, Vector origin) {
|
||||
this.region = region;
|
||||
this.queue = new SparseBitSet();
|
||||
this.visited = new SparseBitSet();
|
||||
this.offsetX = origin.getBlockX();
|
||||
this.offsetZ = origin.getBlockZ();
|
||||
this.queue.set(MathMan.tripleSearchCoords(0, origin.getBlockY(), 0));
|
||||
this.extent = extent;
|
||||
this.maxY = extent.getMaximumPoint().getBlockY();
|
||||
}
|
||||
|
||||
private boolean hasVisited(int x, int y, int z) {
|
||||
return visited.get(MathMan.tripleSearchCoords(x - offsetX, y, z - offsetZ));
|
||||
}
|
||||
|
||||
private void queueVisit(int x, int y, int z) throws RegionOperationException {
|
||||
if (y < 0 || y > maxY) {
|
||||
return;
|
||||
}
|
||||
int ox = x - offsetX;
|
||||
if (ox >= 1024 || ox < -1024) {
|
||||
throw new RegionOperationException("Selection is too large! (1024 blocks wide)");
|
||||
}
|
||||
int oz = z - offsetZ;
|
||||
if (oz >= 1024 || oz < -1024) {
|
||||
throw new RegionOperationException("Selection is too large! (1024 blocks wide)");
|
||||
}
|
||||
int index = MathMan.tripleSearchCoords(ox, y, oz);
|
||||
if (!visited.get(index)) {
|
||||
visited.set(index);
|
||||
queue.set(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
Vector pos = new Vector();
|
||||
Mask mask = region.getMask();
|
||||
int index = 0;
|
||||
while ((index = queue.nextSetBit(index)) != -1 || (index = queue.nextSetBit(0)) != -1) {
|
||||
queue.clear(index);
|
||||
int b1 = (index & 0xFF);
|
||||
int b2 = ((byte) (index >> 8)) & 0x7F;
|
||||
int b3 = ((byte)(index >> 15)) & 0xFF;
|
||||
int b4 = ((byte) (index >> 23)) & 0xFF;
|
||||
int x = offsetX + (((b3 + ((MathMan.unpair8x(b2)) << 8)) << 21) >> 21);
|
||||
int y = b1;
|
||||
int z = offsetZ + (((b4 + ((MathMan.unpair8y(b2)) << 8)) << 21) >> 21);
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
pos.z = z;
|
||||
if (mask.test(pos)) {
|
||||
affected++;
|
||||
region.set(x, y, z);
|
||||
queueVisit(x + 1, y, z);
|
||||
queueVisit(x - 1, y, z);
|
||||
queueVisit(x, y + 1, z);
|
||||
queueVisit(x, y - 1, z);
|
||||
queueVisit(x, y, z + 1);
|
||||
queueVisit(x, y, z - 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
}
|
||||
|
||||
public int getAffected() {
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStatusMessages(List<String> messages) {
|
||||
messages.add(BBC.VISITOR_BLOCK.format(getAffected()));
|
||||
}
|
||||
|
||||
}
|
@ -68,6 +68,20 @@ public class MathMan {
|
||||
return (short) ((x & 15) << 12 | (z & 15) << 8 | y);
|
||||
}
|
||||
|
||||
public static int tripleSearchCoords(int x, int y, int z) {
|
||||
byte b1 = (byte) y;
|
||||
byte b3 = (byte) (x);
|
||||
byte b4 = (byte) (z);
|
||||
int x16 = (x >> 8) & 0x7;
|
||||
int z16 = (z >> 8) & 0x7;
|
||||
byte b2 = MathMan.pair8(x16, z16);
|
||||
return ((b1 & 0xFF)
|
||||
+ ((b2 & 0x7F) << 8)
|
||||
+ ((b3 & 0xFF) << 15)
|
||||
+ ((b4 & 0xFF) << 23))
|
||||
;
|
||||
}
|
||||
|
||||
public static final long chunkXZ2Int(int x, int z) {
|
||||
return (long)x & 4294967295L | ((long)z & 4294967295L) << 32;
|
||||
}
|
||||
@ -96,11 +110,11 @@ public class MathMan {
|
||||
return (byte) (x + (y << 3));
|
||||
}
|
||||
|
||||
public static byte unpair8x(byte value) {
|
||||
public static byte unpair8x(int value) {
|
||||
return (byte) (value & 0x7);
|
||||
}
|
||||
|
||||
public static byte unpair8y(byte value) {
|
||||
public static byte unpair8y(int value) {
|
||||
return (byte) ((value >> 3) & 0x7F);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,14 @@ public class LocationMaskedPlayerWrapper extends PlayerWrapper {
|
||||
this.allowTeleport = allowTeleport;
|
||||
}
|
||||
|
||||
public static Player unwrap(Player object) {
|
||||
if (object instanceof LocationMaskedPlayerWrapper) {
|
||||
return ((LocationMaskedPlayerWrapper) object).getParent();
|
||||
} else {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return position.getYaw();
|
||||
|
Loading…
Reference in New Issue
Block a user