mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 21:56:33 +01:00
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.config.BBC;
|
||||||
import com.boydti.fawe.object.FaweLimit;
|
import com.boydti.fawe.object.FaweLimit;
|
||||||
import com.boydti.fawe.object.RegionWrapper;
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
|
||||||
import com.boydti.fawe.util.WEManager;
|
import com.boydti.fawe.util.WEManager;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
@ -32,6 +31,10 @@ public class ProcessedWEExtent extends FaweRegionExtent {
|
|||||||
this.extent = (AbstractDelegateExtent) parent;
|
this.extent = (AbstractDelegateExtent) parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLimit(FaweLimit other) {
|
||||||
|
this.limit.set(other);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Entity createEntity(final Location location, final BaseEntity entity) {
|
public Entity createEntity(final Location location, final BaseEntity entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package com.boydti.fawe.object.regions;
|
package com.boydti.fawe.object.regions;
|
||||||
|
|
||||||
|
import com.boydti.fawe.object.visitor.FuzzySearch;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.worldedit.BlockVector;
|
import com.sk89q.worldedit.BlockVector;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.function.RegionFunction;
|
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.operation.Operations;
|
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.AbstractRegion;
|
||||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
@ -41,53 +39,14 @@ public class FuzzyRegion extends AbstractRegion {
|
|||||||
return mask;
|
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
|
@Override
|
||||||
public int getArea() {
|
public int getArea() {
|
||||||
return set.cardinality();
|
return set.cardinality();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void select(int x, int y, int z) {
|
public void select(int x, int y, int z) {
|
||||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, new RegionFunction() {
|
FuzzySearch search = new FuzzySearch(this, extent, new Vector(x, y, z));
|
||||||
@Override
|
Operations.completeBlindly(search);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -105,13 +64,13 @@ public class FuzzyRegion extends AbstractRegion {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockVector next() {
|
public BlockVector next() {
|
||||||
int b1 = ((byte) index) & 0xFF;
|
int b1 = (index & 0xFF);
|
||||||
int b2 = ((byte) (index >> 8)) & 0xFF;
|
int b2 = ((byte) (index >> 8)) & 0x7F;
|
||||||
int b3 = ((byte)(index >> 16)) & 0xFF;
|
int b3 = ((byte)(index >> 15)) & 0xFF;
|
||||||
byte b4 = (byte) (index >> 24);
|
int b4 = ((byte) (index >> 23)) & 0xFF;
|
||||||
pos.x = offsetX + (((b2 + ((MathMan.unpair8x(b4)) << 8)) << 21) >> 21);
|
pos.x = offsetX + (((b3 + ((MathMan.unpair8x(b2)) << 8)) << 21) >> 21);
|
||||||
pos.y = offsetY + b1;
|
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;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +83,8 @@ public class FuzzyRegion extends AbstractRegion {
|
|||||||
|
|
||||||
public void set(int x, int y, int z) throws RegionOperationException{
|
public void set(int x, int y, int z) throws RegionOperationException{
|
||||||
if (populated) {
|
if (populated) {
|
||||||
if (++count > 1048576) {
|
if (++count > 16777216) {
|
||||||
throw new RegionOperationException("Selection is too large! (1048576 blocks)");
|
throw new RegionOperationException("Selection is too large! (16777216 blocks)");
|
||||||
}
|
}
|
||||||
x -= offsetX;
|
x -= offsetX;
|
||||||
y -= offsetY;
|
y -= offsetY;
|
||||||
@ -137,7 +96,7 @@ public class FuzzyRegion extends AbstractRegion {
|
|||||||
z = 0;
|
z = 0;
|
||||||
populated = true;
|
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) {
|
if (x >= 1024 || x <= -1024 || z >= 1024 || z <= -1024) {
|
||||||
throw new RegionOperationException("Selection is too large! (1024 blocks wide)");
|
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) {
|
public boolean contains(int x, int y, int z) {
|
||||||
try {
|
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) {
|
} catch (IndexOutOfBoundsException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@ -171,12 +130,12 @@ public class FuzzyRegion extends AbstractRegion {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector getMinimumPoint() {
|
public Vector getMinimumPoint() {
|
||||||
return new Vector(minX, minY, minZ);
|
return new Vector(minX + offsetX, minY + offsetY, minZ + offsetZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector getMaximumPoint() {
|
public Vector getMaximumPoint() {
|
||||||
return new Vector(maxX, maxY, maxZ);
|
return new Vector(maxX + offsetX, maxY + offsetY, maxZ + offsetZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -14,7 +14,6 @@ import com.sk89q.worldedit.Vector;
|
|||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.regions.RegionSelector;
|
import com.sk89q.worldedit.regions.RegionSelector;
|
||||||
@ -35,7 +34,7 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
|
|||||||
.player(FawePlayer.wrap(player))
|
.player(FawePlayer.wrap(player))
|
||||||
.changeSetNull()
|
.changeSetNull()
|
||||||
.checkMemory(false)
|
.checkMemory(false)
|
||||||
.autoQueue(false)
|
.autoQueue(true)
|
||||||
.build());
|
.build());
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.region = new FuzzyRegion(world, getExtent(), mask);
|
this.region = new FuzzyRegion(world, getExtent(), mask);
|
||||||
@ -55,7 +54,7 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
|
|||||||
.player(FawePlayer.wrap(player))
|
.player(FawePlayer.wrap(player))
|
||||||
.changeSetNull()
|
.changeSetNull()
|
||||||
.checkMemory(false)
|
.checkMemory(false)
|
||||||
.autoQueue(false)
|
.autoQueue(true)
|
||||||
.build();
|
.build();
|
||||||
new ExtentTraverser(this).setNext(extent);
|
new ExtentTraverser(this).setNext(extent);
|
||||||
this.region.setWorld(world);
|
this.region.setWorld(world);
|
||||||
@ -69,13 +68,10 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean selectPrimary(Vector position, SelectorLimits limits) {
|
public boolean selectPrimary(Vector position, SelectorLimits limits) {
|
||||||
|
setWorld(getWorld());
|
||||||
|
new MaskTraverser(getMask()).reset(getExtent());
|
||||||
positions.clear();
|
positions.clear();
|
||||||
positions.add(position);
|
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 = new FuzzyRegion(getWorld(), getExtent(), getMask());
|
||||||
this.region.select((int) position.x, (int) position.y, (int) position.z);
|
this.region.select((int) position.x, (int) position.y, (int) position.z);
|
||||||
return true;
|
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);
|
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) {
|
public static final long chunkXZ2Int(int x, int z) {
|
||||||
return (long)x & 4294967295L | ((long)z & 4294967295L) << 32;
|
return (long)x & 4294967295L | ((long)z & 4294967295L) << 32;
|
||||||
}
|
}
|
||||||
@ -96,11 +110,11 @@ public class MathMan {
|
|||||||
return (byte) (x + (y << 3));
|
return (byte) (x + (y << 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte unpair8x(byte value) {
|
public static byte unpair8x(int value) {
|
||||||
return (byte) (value & 0x7);
|
return (byte) (value & 0x7);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte unpair8y(byte value) {
|
public static byte unpair8y(int value) {
|
||||||
return (byte) ((value >> 3) & 0x7F);
|
return (byte) ((value >> 3) & 0x7F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,14 @@ public class LocationMaskedPlayerWrapper extends PlayerWrapper {
|
|||||||
this.allowTeleport = allowTeleport;
|
this.allowTeleport = allowTeleport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Player unwrap(Player object) {
|
||||||
|
if (object instanceof LocationMaskedPlayerWrapper) {
|
||||||
|
return ((LocationMaskedPlayerWrapper) object).getParent();
|
||||||
|
} else {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getYaw() {
|
public double getYaw() {
|
||||||
return position.getYaw();
|
return position.getYaw();
|
||||||
|
Loading…
Reference in New Issue
Block a user