geforkt von Mirrors/FastAsyncWorldEdit
scanchunk
Dieser Commit ist enthalten in:
Ursprung
d603f45063
Commit
459629a2f2
@ -181,13 +181,12 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
// Initialize
|
||||
chunk.init(queue, X, Z);
|
||||
|
||||
chunk = newFilter.applyChunk(chunk, region);
|
||||
|
||||
if (chunk == null) continue;
|
||||
|
||||
if (block == null) block = queue.initFilterBlock();
|
||||
chunk.filter(newFilter, block, region, mbv1, mbv2);
|
||||
|
||||
IChunk newChunk = newFilter.applyChunk(chunk, region);
|
||||
if (newChunk != null) {
|
||||
chunk = newChunk;
|
||||
if (block == null) block = queue.initFilterBlock();
|
||||
chunk.filter(newFilter, block, region, mbv1, mbv2);
|
||||
}
|
||||
queue.submit(chunk);
|
||||
}
|
||||
queue.flush();
|
||||
|
@ -19,10 +19,8 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
|
||||
private final Mask mask;
|
||||
private BlockVectorSet set = new BlockVectorSet();
|
||||
private boolean populated;
|
||||
private int minX, minY, minZ, maxX, maxY, maxZ;
|
||||
private Extent extent;
|
||||
private int count = 0;
|
||||
|
||||
{
|
||||
minX = minY = minZ = Integer.MAX_VALUE;
|
||||
@ -59,7 +57,7 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return (Iterator) set.iterator();
|
||||
return set.iterator();
|
||||
}
|
||||
|
||||
private final void setMinMax(int x, int y, int z) {
|
||||
|
@ -6,6 +6,7 @@ import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
@ -39,14 +40,14 @@ public class AboveVisitor extends RecursiveVisitor {
|
||||
|
||||
this.baseY = baseY;
|
||||
|
||||
Collection<BlockVector3> directions = getDirections();
|
||||
directions.clear();
|
||||
directions.add(BlockVector3.at(1, 0, 0));
|
||||
directions.add(BlockVector3.at(-1, 0, 0));
|
||||
directions.add(BlockVector3.at(0, 0, 1));
|
||||
directions.add(BlockVector3.at(0, 0, -1));
|
||||
directions.add(BlockVector3.at(0, 1, 0));
|
||||
directions.add(BlockVector3.at(0, -1, 0));
|
||||
setDirections(
|
||||
BlockVector3.at(1, 0, 0),
|
||||
BlockVector3.at(-1, 0, 0),
|
||||
BlockVector3.at(0, 0, 1),
|
||||
BlockVector3.at(0, 0, -1),
|
||||
BlockVector3.at(0, 1, 0),
|
||||
BlockVector3.at(0, -1, 0)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,6 +23,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
@ -73,7 +74,7 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
}
|
||||
|
||||
private final RegionFunction function;
|
||||
private List<BlockVector3> directions = new ArrayList<>();
|
||||
private BlockVector3[] directions;
|
||||
private BlockVectorSet visited;
|
||||
private final MappedFaweQueue mFaweQueue;
|
||||
private BlockVectorSet queue;
|
||||
@ -96,23 +97,18 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
this.queue = new BlockVectorSet();
|
||||
this.visited = new BlockVectorSet();
|
||||
this.function = function;
|
||||
this.directions.addAll(Arrays.asList(DEFAULT_DIRECTIONS));
|
||||
this.directions = DEFAULT_DIRECTIONS;
|
||||
this.maxDepth = maxDepth;
|
||||
}
|
||||
|
||||
public void setDirections(List<BlockVector3> directions) {
|
||||
public void setDirections(BlockVector3... directions) {
|
||||
this.directions = directions;
|
||||
}
|
||||
|
||||
private IntegerTrio[] getIntDirections() {
|
||||
IntegerTrio[] array = new IntegerTrio[directions.size()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
BlockVector3 dir = directions.get(i);
|
||||
array[i] = new IntegerTrio(dir.getBlockX(), dir.getBlockY(), dir.getBlockZ());
|
||||
}
|
||||
return array;
|
||||
public void setDirections(Collection<BlockVector3> directions) {
|
||||
setDirections(directions.toArray(new BlockVector3[0]));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of directions will be visited.
|
||||
*
|
||||
@ -121,34 +117,36 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
* unit vectors. An example of a valid direction is
|
||||
* {@code BlockVector3.at(1, 0, 1)}.</p>
|
||||
*
|
||||
* <p>The list of directions can be cleared.</p>
|
||||
*
|
||||
* @return the list of directions
|
||||
*/
|
||||
protected Collection<BlockVector3> getDirections() {
|
||||
return directions;
|
||||
public Collection<BlockVector3> getDirections() {
|
||||
return Arrays.asList(directions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the directions along the axes as directions to visit.
|
||||
*/
|
||||
protected void addAxes() {
|
||||
directions.add(BlockVector3.at(0, -1, 0));
|
||||
directions.add(BlockVector3.at(0, 1, 0));
|
||||
directions.add(BlockVector3.at(-1, 0, 0));
|
||||
directions.add(BlockVector3.at(1, 0, 0));
|
||||
directions.add(BlockVector3.at(0, 0, -1));
|
||||
directions.add(BlockVector3.at(0, 0, 1));
|
||||
public void addAxes() {
|
||||
HashSet<BlockVector3> set = new HashSet<>(Arrays.asList(directions));
|
||||
set.add(BlockVector3.at(0, -1, 0));
|
||||
set.add(BlockVector3.at(0, 1, 0));
|
||||
set.add(BlockVector3.at(-1, 0, 0));
|
||||
set.add(BlockVector3.at(1, 0, 0));
|
||||
set.add(BlockVector3.at(0, 0, -1));
|
||||
set.add(BlockVector3.at(0, 0, 1));
|
||||
setDirections(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the diagonal directions as directions to visit.
|
||||
*/
|
||||
protected void addDiagonal() {
|
||||
directions.add(BlockVector3.at(1, 0, 1));
|
||||
directions.add(BlockVector3.at(-1, 0, -1));
|
||||
directions.add(BlockVector3.at(1, 0, -1));
|
||||
directions.add(BlockVector3.at(-1, 0, 1));
|
||||
public void addDiagonal() {
|
||||
HashSet<BlockVector3> set = new HashSet<>(Arrays.asList(directions));
|
||||
set.add(BlockVector3.at(1, 0, 1));
|
||||
set.add(BlockVector3.at(-1, 0, -1));
|
||||
set.add(BlockVector3.at(1, 0, -1));
|
||||
set.add(BlockVector3.at(-1, 0, 1));
|
||||
setDirections(set);
|
||||
}
|
||||
|
||||
public void visit(final BlockVector3 pos) {
|
||||
@ -159,12 +157,6 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
}
|
||||
}
|
||||
|
||||
public void resetVisited() {
|
||||
queue.clear();
|
||||
visited.clear();
|
||||
affected = 0;
|
||||
}
|
||||
|
||||
public void setVisited(BlockVectorSet set) {
|
||||
this.visited = set;
|
||||
}
|
||||
@ -180,21 +172,6 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
public void setMaxBranch(int maxBranch) {
|
||||
this.maxBranch = maxBranch;
|
||||
}
|
||||
/**
|
||||
* Try to visit the given 'to' location.
|
||||
*
|
||||
* @param from the origin block
|
||||
* @param to the block under question
|
||||
*/
|
||||
private void visit(BlockVector3 from, BlockVector3 to) {
|
||||
BlockVector3 blockVector = to;
|
||||
if (!visited.contains(blockVector)) {
|
||||
visited.add(blockVector);
|
||||
if (isVisitable(from, to)) {
|
||||
queue.add(blockVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given 'to' block should be visited, starting from the
|
||||
@ -220,7 +197,7 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
MutableBlockVector3 mutable = new MutableBlockVector3();
|
||||
// MutableBlockVector3 mutable2 = new MutableBlockVector3();
|
||||
boolean shouldTrim = false;
|
||||
IntegerTrio[] dirs = getIntDirections();
|
||||
BlockVector3[] dirs = directions;
|
||||
BlockVectorSet tempQueue = new BlockVectorSet();
|
||||
BlockVectorSet chunkLoadSet = new BlockVectorSet();
|
||||
for (currentDepth = 0; !queue.isEmpty() && currentDepth <= maxDepth; currentDepth++) {
|
||||
@ -228,11 +205,11 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
int cx = Integer.MIN_VALUE;
|
||||
int cz = Integer.MIN_VALUE;
|
||||
for (BlockVector3 from : queue) {
|
||||
for (IntegerTrio direction : dirs) {
|
||||
int x = from.getBlockX() + direction.x;
|
||||
int z = from.getBlockZ() + direction.z;
|
||||
for (BlockVector3 direction : dirs) {
|
||||
int x = from.getBlockX() + direction.getX();
|
||||
int z = from.getBlockZ() + direction.getZ();
|
||||
if (cx != (cx = x >> 4) || cz != (cz = z >> 4)) {
|
||||
int y = from.getBlockY() + direction.y;
|
||||
int y = from.getBlockY() + direction.getY();
|
||||
if (y < 0 || y >= 256) {
|
||||
continue;
|
||||
}
|
||||
@ -249,13 +226,13 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
for (BlockVector3 from : queue) {
|
||||
if (function.apply(from)) affected++;
|
||||
for (int i = 0, j = 0; i < dirs.length && j < maxBranch; i++) {
|
||||
IntegerTrio direction = dirs[i];
|
||||
int y = from.getBlockY() + direction.y;
|
||||
BlockVector3 direction = dirs[i];
|
||||
int y = from.getBlockY() + direction.getY();
|
||||
if (y < 0 || y >= 256) {
|
||||
continue;
|
||||
}
|
||||
int x = from.getBlockX() + direction.x;
|
||||
int z = from.getBlockZ() + direction.z;
|
||||
int x = from.getBlockX() + direction.getX();
|
||||
int z = from.getBlockZ() + direction.getZ();
|
||||
if (!visited.contains(x, y, z)) {
|
||||
if (isVisitable(from, BlockVector3.at(x, y, z))) {
|
||||
j++;
|
||||
|
@ -51,14 +51,15 @@ public class DirectionalVisitor extends RecursiveVisitor {
|
||||
checkNotNull(mask);
|
||||
this.origin = origin;
|
||||
this.dirVec = direction;
|
||||
final Collection<BlockVector3> directions = this.getDirections();
|
||||
directions.clear();
|
||||
directions.add(BlockVector3.at(1, 0, 0));
|
||||
directions.add(BlockVector3.at(-1, 0, 0));
|
||||
directions.add(BlockVector3.at(0, 0, 1));
|
||||
directions.add(BlockVector3.at(0, 0, -1));
|
||||
directions.add(BlockVector3.at(0, -1, 0));
|
||||
directions.add(BlockVector3.at(0, 1, 0));
|
||||
|
||||
setDirections(
|
||||
BlockVector3.at(1, 0, 0),
|
||||
BlockVector3.at(-1, 0, 0),
|
||||
BlockVector3.at(0, 0, 1),
|
||||
BlockVector3.at(0, 0, -1),
|
||||
BlockVector3.at(0, -1, 0),
|
||||
BlockVector3.at(0, 1, 0)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,13 +60,13 @@ public class DownwardVisitor extends RecursiveVisitor {
|
||||
checkNotNull(mask);
|
||||
this.baseY = baseY;
|
||||
|
||||
Collection<BlockVector3> directions = getDirections();
|
||||
directions.clear();
|
||||
directions.add(BlockVector3.at(1, 0, 0));
|
||||
directions.add(BlockVector3.at(-1, 0, 0));
|
||||
directions.add(BlockVector3.at(0, 0, 1));
|
||||
directions.add(BlockVector3.at(0, 0, -1));
|
||||
directions.add(BlockVector3.at(0, -1, 0));
|
||||
setDirections(
|
||||
BlockVector3.at(1, 0, 0),
|
||||
BlockVector3.at(-1, 0, 0),
|
||||
BlockVector3.at(0, 0, 1),
|
||||
BlockVector3.at(0, 0, -1),
|
||||
BlockVector3.at(0, -1, 0)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,13 +46,14 @@ public class NonRisingVisitor extends RecursiveVisitor {
|
||||
|
||||
public NonRisingVisitor(Mask mask, RegionFunction function, int depth, HasFaweQueue hasFaweQueue) {
|
||||
super(mask, function, depth, hasFaweQueue);
|
||||
Collection<BlockVector3> directions = getDirections();
|
||||
directions.clear();
|
||||
directions.add(BlockVector3.at(1, 0, 0));
|
||||
directions.add(BlockVector3.at(-1, 0, 0));
|
||||
directions.add(BlockVector3.at(0, 0, 1));
|
||||
directions.add(BlockVector3.at(0, 0, -1));
|
||||
directions.add(BlockVector3.at(0, -1, 0));
|
||||
|
||||
setDirections(
|
||||
BlockVector3.at(1, 0, 0),
|
||||
BlockVector3.at(-1, 0, 0),
|
||||
BlockVector3.at(0, 0, 1),
|
||||
BlockVector3.at(0, 0, -1),
|
||||
BlockVector3.at(0, -1, 0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,151 @@
|
||||
package com.sk89q.worldedit.function.visitor;
|
||||
|
||||
import com.boydti.fawe.example.MappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.HasFaweQueue;
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A chunk based search algorithm
|
||||
*/
|
||||
public class ScanChunk {
|
||||
private static final int MAX_QUEUE = 34816;
|
||||
public static final BlockVector3[] DEFAULT_DIRECTIONS = new BlockVector3[6];
|
||||
public static final BlockVector3[] DIAGONAL_DIRECTIONS;
|
||||
|
||||
static {
|
||||
DEFAULT_DIRECTIONS[0] = (BlockVector3.at(0, -1, 0));
|
||||
DEFAULT_DIRECTIONS[1] = (BlockVector3.at(0, 1, 0));
|
||||
DEFAULT_DIRECTIONS[2] = (BlockVector3.at(-1, 0, 0));
|
||||
DEFAULT_DIRECTIONS[3] = (BlockVector3.at(1, 0, 0));
|
||||
DEFAULT_DIRECTIONS[4] = (BlockVector3.at(0, 0, -1));
|
||||
DEFAULT_DIRECTIONS[5] = (BlockVector3.at(0, 0, 1));
|
||||
List<BlockVector3> list = new ArrayList<>();
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
for (int z = -1; z <= 1; z++) {
|
||||
if (x != 0 || y != 0 || z != 0) {
|
||||
BlockVector3 pos = BlockVector3.at(x, y, z);
|
||||
if (!list.contains(pos)) {
|
||||
list.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(list, new Comparator<BlockVector3>() {
|
||||
@Override
|
||||
public int compare(BlockVector3 o1, BlockVector3 o2) {
|
||||
return (int) Math.signum(o1.lengthSq() - o2.lengthSq());
|
||||
}
|
||||
});
|
||||
DIAGONAL_DIRECTIONS = list.toArray(new BlockVector3[list.size()]);
|
||||
}
|
||||
|
||||
private final RegionFunction function;
|
||||
private final BlockVector3[] directions;
|
||||
private final Long2ObjectOpenHashMap<long[][]> visited;
|
||||
private final Long2ObjectOpenHashMap<char[]> queues;
|
||||
|
||||
public ScanChunk(final RegionFunction function) {
|
||||
this.function = function;
|
||||
this.directions = DEFAULT_DIRECTIONS;
|
||||
|
||||
this.queues = new Long2ObjectOpenHashMap<>();
|
||||
this.visited = new Long2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
public static final long pairInt(int x, int y) {
|
||||
return (((long) x) << 32) | (y & 0xffffffffL);
|
||||
}
|
||||
|
||||
public boolean isVisited(int x, int y, int z) {
|
||||
int X = x >> 4;
|
||||
int Z = z >> 4;
|
||||
long pair = pairInt(X, Z);
|
||||
long[][] chunk = visited.get(pair);
|
||||
if (chunk == null) return false;
|
||||
int layer = y >> 4;
|
||||
long[] section = chunk[layer];
|
||||
if (section == null) return false;
|
||||
return get(section, getLocalIndex(x & 15, y & 15, z & 15));
|
||||
}
|
||||
|
||||
public void start(int x, int y, int z) {
|
||||
if (!isVisited(x, y, z)) {
|
||||
queue(x, y, z);
|
||||
visit(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
public void visit(int x, int y, int z) {
|
||||
int X = x >> 4;
|
||||
int Z = z >> 4;
|
||||
long pair = pairInt(X, Z);
|
||||
long[][] chunk = visited.get(pair);
|
||||
if (chunk == null) {
|
||||
visited.put(pair, chunk = new long[16][]);
|
||||
}
|
||||
int layer = y >> 4;
|
||||
long[] section = chunk[layer];
|
||||
if (section == null) {
|
||||
chunk[layer] = section = new long[64];
|
||||
}
|
||||
set(section, getLocalIndex(x & 15, y & 15, z & 15));
|
||||
}
|
||||
|
||||
public void queue(int x, int y, int z) {
|
||||
int X = x >> 4;
|
||||
int Z = z >> 4;
|
||||
long pair = pairInt(X, Z);
|
||||
char[] queue = queues.get(pair);
|
||||
if (queue == null) {
|
||||
queue = queues.put(pair, queue = new char[MAX_QUEUE + 2]);
|
||||
queue[0] = 2;
|
||||
queue[1] = 2;
|
||||
}
|
||||
if (queue[1] >= queue.length) {
|
||||
queue[1] = 2;
|
||||
}
|
||||
queue[queue[1]++] = getLocalIndex(x & 15, y, z & 15);
|
||||
}
|
||||
|
||||
public void process() {
|
||||
LongArraySet set = new LongArraySet();
|
||||
while (!queues.isEmpty()) {
|
||||
ObjectIterator<Long2ObjectMap.Entry<char[]>> iter = queues.long2ObjectEntrySet().fastIterator();
|
||||
Long2ObjectMap.Entry<char[]> entry = iter.next();
|
||||
long index = entry.getLongKey();
|
||||
int X = MathMan.unpairIntX(index);
|
||||
int Z = MathMan.unpairIntY(index);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(long[] bits, int i) {
|
||||
bits[i >> 6] |= (1L << (i & 0x3F));
|
||||
}
|
||||
|
||||
public boolean get(long[] bits, final int i) {
|
||||
return (bits[i >> 6] & (1L << (i & 0x3F))) != 0;
|
||||
}
|
||||
|
||||
public char getLocalIndex(int x, int y, int z) {
|
||||
return (char) (y + (x << 8) + (z << 12));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -44,6 +44,7 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
*/
|
||||
private Vector3 radius;
|
||||
private Vector3 radiusSqr;
|
||||
private Vector3 inverseRadius;
|
||||
private int radiusLengthSqr;
|
||||
private boolean sphere;
|
||||
|
||||
@ -136,7 +137,7 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
public void contract(BlockVector3... changes) throws RegionOperationException {
|
||||
center = center.subtract(calculateDiff(changes));
|
||||
Vector3 newRadius = radius.subtract(calculateChanges(changes));
|
||||
radius = Vector3.at(1.5, 1.5, 1.5).getMaximum(newRadius);
|
||||
setRadius(Vector3.at(1.5, 1.5, 1.5).getMaximum(newRadius));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -187,6 +188,7 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
} else {
|
||||
this.sphere = false;
|
||||
}
|
||||
inverseRadius = Vector3.ONE.divide(radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -233,9 +235,9 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
if (sphere) {
|
||||
return cx2 + cy2 + cz2 <= radiusLengthSqr;
|
||||
}
|
||||
double cxd = (double) cx / radius.getBlockX();
|
||||
double cyd = (double) cy / radius.getBlockY();
|
||||
double czd = (double) cz / radius.getBlockZ();
|
||||
double cxd = cx * inverseRadius.getX();
|
||||
double cyd = cy * inverseRadius.getY();
|
||||
double czd = cz * inverseRadius.getZ();
|
||||
return cxd * cxd + cyd * cyd + czd * czd <= 1;
|
||||
}
|
||||
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren