mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-06 04:46:40 +00:00
wip on 1.14
This commit is contained in:
@ -19,6 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.boydti.fawe.beta.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
@ -394,14 +399,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
public boolean contains(int x, int z) {
|
||||
return x >= this.minX && x <= this.maxX && z >= this.minZ && z <= this.maxZ;
|
||||
}
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return position.containedWithin(min, max);
|
||||
}
|
||||
@NotNull @Override
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
if (Settings.IMP.HISTORY.COMPRESSION_LEVEL >= 9 || useOldIterator) {
|
||||
return iterator_old();
|
||||
@ -612,5 +611,50 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
return new CuboidRegion(origin.subtract(size), origin.add(size));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
return maxY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set) {
|
||||
int X = chunk.getX();
|
||||
int Z = chunk.getZ();
|
||||
block = block.init(X, Z, get);
|
||||
|
||||
if ((minX + 15) >> 4 <= X && (maxX - 15) >> 4 >= X && (minZ + 15) >> 4 <= Z && (maxZ - 15) >> 4 >= Z) {
|
||||
filter(chunk, filter, block, get, set, minY, maxY);
|
||||
return;
|
||||
}
|
||||
int localMinX = Math.max(minX, X << 4) & 15;
|
||||
int localMaxX = Math.min(maxX, 15 + X << 4) & 15;
|
||||
int localMinZ = Math.max(minZ, Z << 4) & 15;
|
||||
int localMaxZ = Math.min(maxZ, 15 + Z << 4) & 15;
|
||||
|
||||
int yStart = (minY & 15);
|
||||
int yEnd = (maxY & 15);
|
||||
|
||||
int minSection = minY >> 4;
|
||||
int maxSection = maxY >> 4;
|
||||
if (minSection == maxSection) {
|
||||
filter(chunk, filter, block, get, set, minSection, localMinX, yStart, localMinZ, localMaxX, yEnd, localMaxZ);
|
||||
return;
|
||||
}
|
||||
if (yStart != 0) {
|
||||
filter(chunk, filter, block, get, set, minSection, localMinX, yStart, localMinZ, localMaxX, 15, localMaxZ);
|
||||
minSection++;
|
||||
}
|
||||
if (yEnd != 15) {
|
||||
filter(chunk, filter, block, get, set, minSection, localMinX, 0, localMinZ, localMaxX, 15, localMaxZ);
|
||||
maxSection--;
|
||||
}
|
||||
for (int layer = minSection; layer < maxSection; layer++) {
|
||||
filter(chunk, filter, block, get, set, layer, localMinX, yStart, localMinZ, localMaxX, yEnd, localMaxZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,12 @@
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.beta.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -287,26 +293,22 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
|
||||
minY += changeY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a point is inside this region.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
final int blockY = position.getBlockY();
|
||||
if (blockY < minY || blockY > maxY) {
|
||||
public boolean contains(int x, int y, int z) {
|
||||
if (y < minY || y > maxY) {
|
||||
return false;
|
||||
}
|
||||
//todo the following lines can possibly be removed and replaced with upstream
|
||||
int px = position.getBlockX();
|
||||
int pz = position.getBlockZ();
|
||||
return contains(x, z);
|
||||
}
|
||||
|
||||
double dx = Math.abs(px - center.getBlockX()) * radiusInverse.getX();
|
||||
double dz = Math.abs(pz - center.getBlockZ()) * radiusInverse.getZ();
|
||||
@Override
|
||||
public boolean contains(int x, int z) {
|
||||
double dx = Math.abs(x - center.getBlockX()) * radiusInverse.getX();
|
||||
double dz = Math.abs(z - center.getBlockZ()) * radiusInverse.getZ();
|
||||
|
||||
return dx * dx + dz * dz <= 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the height of the cylinder to fit the specified Y.
|
||||
*
|
||||
@ -361,6 +363,16 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
|
||||
return Polygons.polygonizeCylinder(center, radius, maxPoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
return maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new instance with the given center and radius in the X and Z
|
||||
* axes with a Y that extends from the bottom of the extent to the top
|
||||
@ -380,4 +392,16 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
|
||||
return new CylinderRegion(center, radiusVec, minY, maxY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(final IChunk chunk, final Filter filter, final ChunkFilterBlock block, final IChunkGet get, final IChunkSet set) {
|
||||
int bcx = chunk.getX() >> 4;
|
||||
int bcz = chunk.getZ() >> 4;
|
||||
int tcx = bcx + 15;
|
||||
int tcz = bcz + 15;
|
||||
if (contains(bcx, bcz) && contains(tcx, tcz)) {
|
||||
filter(chunk, filter, block, get, set, minY, maxY);
|
||||
return;
|
||||
}
|
||||
super.filter(chunk, filter, block, get, set);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
|
||||
import com.boydti.fawe.beta.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
@ -44,6 +51,7 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
private Vector3 radius;
|
||||
|
||||
private Vector3 radiusSqr;
|
||||
private Vector3 inverseRadius;
|
||||
private int radiusLengthSqr;
|
||||
private boolean sphere;
|
||||
|
||||
@ -184,6 +192,7 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
} else {
|
||||
this.sphere = false;
|
||||
}
|
||||
inverseRadius = Vector3.ONE.divide(radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -210,30 +219,50 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
return chunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int x, int y, int z) {
|
||||
int cx = x - center.getBlockX();
|
||||
int cx2 = cx * cx;
|
||||
if (cx2 > radiusSqr.getBlockX()) {
|
||||
return false;
|
||||
}
|
||||
int cz = z - center.getBlockZ();
|
||||
int cz2 = cz * cz;
|
||||
if (cz2 > radiusSqr.getBlockZ()) {
|
||||
return false;
|
||||
}
|
||||
int cy = y - center.getBlockY();
|
||||
int cy2 = cy * cy;
|
||||
if (radiusSqr.getBlockY() < 255 && cy2 > radiusSqr.getBlockY()) {
|
||||
return false;
|
||||
}
|
||||
if (sphere) {
|
||||
return cx2 + cy2 + cz2 <= radiusLengthSqr;
|
||||
}
|
||||
double cxd = cx2 * inverseRadius.getX();
|
||||
double cyd = cy2 * inverseRadius.getY();
|
||||
double czd = cz2 * inverseRadius.getZ();
|
||||
return cxd + cyd + czd <= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
int cx = position.getBlockX() - center.getBlockX();
|
||||
public boolean contains(int x, int z) {
|
||||
int cx = x - center.getBlockX();
|
||||
int cx2 = cx * cx;
|
||||
if (cx2 > radiusSqr.getBlockX()) {
|
||||
return false;
|
||||
}
|
||||
int cz = position.getBlockZ() - center.getBlockZ();
|
||||
int cz = z - center.getBlockZ();
|
||||
int cz2 = cz * cz;
|
||||
if (cz2 > radiusSqr.getBlockZ()) {
|
||||
return false;
|
||||
}
|
||||
int cy = position.getBlockY() - center.getBlockY();
|
||||
int cy2 = cy * cy;
|
||||
if (radiusSqr.getBlockY() < 255 && cy2 > radiusSqr.getBlockY()) {
|
||||
return false;
|
||||
}
|
||||
if (sphere) {
|
||||
return cx2 + cy2 + cz2 <= radiusLengthSqr;
|
||||
return cx2 + cz2 <= radiusLengthSqr;
|
||||
}
|
||||
double cxd = (double) cx / radius.getBlockX();
|
||||
double cyd = (double) cy / radius.getBlockY();
|
||||
double czd = (double) cz / radius.getBlockZ();
|
||||
return cxd * cxd + cyd * cyd + czd * czd <= 1;
|
||||
double cxd = cx2 * inverseRadius.getX();
|
||||
double czd = cz2 * inverseRadius.getZ();
|
||||
return cxd + czd <= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,4 +285,113 @@ public class EllipsoidRegion extends AbstractRegion {
|
||||
return (EllipsoidRegion) super.clone();
|
||||
}
|
||||
|
||||
private void filterSpherePartial(int y1, int y2, int bx, int bz, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set) {
|
||||
int sectionStart = y1 >> 4;
|
||||
int sectionEnd = y2 >> 4;
|
||||
|
||||
}
|
||||
|
||||
private void filterSpherePartial(int layer, int y1, int y2, int bx, int bz, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set) {
|
||||
int cx = center.getBlockX();
|
||||
int cy = center.getBlockY();
|
||||
int cz = center.getBlockZ();
|
||||
|
||||
block.init(get, set, layer);
|
||||
|
||||
int by = layer << 4;
|
||||
int diffY;
|
||||
for (int y = y1, yy = by + y1; y <= y2; y++, yy++) {
|
||||
diffY = cy - yy;
|
||||
int remainderY = radiusLengthSqr - (diffY * diffY);
|
||||
if (remainderY >= 0) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int zz = z + bz;
|
||||
int diffZ = cz - zz;
|
||||
int remainderZ = remainderY - (diffZ * diffZ);
|
||||
if (remainderZ >= 0) {
|
||||
int diffX = MathMan.usqrt(remainderZ);
|
||||
int minX = Math.max(0, cx - diffX - bx);
|
||||
int maxX = Math.min(15, cx + diffX - bx);
|
||||
if (minX != maxX) {
|
||||
block.filter(filter, minX, y, z, maxX, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(IChunk chunk, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set) {
|
||||
// Check bounds
|
||||
// This needs to be able to perform 50M blocks/sec otherwise it becomes a bottleneck
|
||||
int cx = center.getBlockX();
|
||||
int cz = center.getBlockZ();
|
||||
int bx = chunk.getX() << 4;
|
||||
int bz = chunk.getZ() << 4;
|
||||
int tx = bx + 15;
|
||||
int tz = bz + 15;
|
||||
int cx1 = bx - cx;
|
||||
int cx2 = tx - cx;
|
||||
int cxMax, cxMin;
|
||||
if (cx1 < cx2) {
|
||||
cxMin = cx1;
|
||||
cxMax = cx2;
|
||||
} else {
|
||||
cxMin = cx2;
|
||||
cxMax = cx1;
|
||||
}
|
||||
int cxMin2 = cxMin * cxMin;
|
||||
int cxMax2 = cxMax * cxMax;
|
||||
int cz1 = bz - cz;
|
||||
int cz2 = tz - cz;
|
||||
int czMax, czMin;
|
||||
if (cz1 < cz2) {
|
||||
czMin = cz1;
|
||||
czMax = cz2;
|
||||
} else {
|
||||
czMin = cz2;
|
||||
czMax = cz1;
|
||||
}
|
||||
int czMin2 = czMin * czMin;
|
||||
int czMax2 = czMax * czMax;
|
||||
|
||||
|
||||
if (sphere) {
|
||||
// Does not contain chunk
|
||||
if (cxMin2 + czMin2 >= radiusLengthSqr) {
|
||||
return;
|
||||
}
|
||||
int diffY2 = radiusLengthSqr - cxMax2 - czMax2;
|
||||
// (shortcut) Contains all of certain layers
|
||||
if (diffY2 >= 0) {
|
||||
// Get the solid layers
|
||||
int cy = center.getBlockY();
|
||||
int diffYFull = MathMan.usqrt(diffY2);
|
||||
int yBotFull = Math.max(0, cy - diffYFull);
|
||||
int yTopFull = Math.min(255, cy + diffYFull);
|
||||
// Set those layers
|
||||
filter(chunk, filter, block, get, set, yBotFull, yTopFull);
|
||||
|
||||
// Fill the remaining layers
|
||||
if (yBotFull != 0 || yTopFull != 255) {
|
||||
int diffYPartial = MathMan.usqrt(radiusLengthSqr - cxMin * cxMin - czMin * czMin);
|
||||
|
||||
if (yBotFull != 0) {
|
||||
int yBotPartial = Math.max(0, cy - diffYPartial);
|
||||
filterSpherePartial(yBotPartial, yBotFull - 1, bx, bz, filter, block, get, set);
|
||||
}
|
||||
|
||||
if (yTopFull != 255) {
|
||||
int yTopPartial = Math.min(255, cy + diffYPartial);
|
||||
filterSpherePartial(yTopFull + 1, yTopPartial - 1, bx, bz, filter, block, get, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
super.filter(chunk, filter, block, get, set); // TODO optimize non spheres
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,20 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.boydti.fawe.beta.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -128,7 +136,9 @@ public interface Region extends Iterable<BlockVector3>, Cloneable {
|
||||
* @param position the position
|
||||
* @return true if contained
|
||||
*/
|
||||
boolean contains(BlockVector3 position);
|
||||
default boolean contains(BlockVector3 position) {
|
||||
return contains(position.getX(), position.getY(), position.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of chunks.
|
||||
@ -172,4 +182,63 @@ public interface Region extends Iterable<BlockVector3>, Cloneable {
|
||||
* @return the points.
|
||||
*/
|
||||
List<BlockVector2> polygonize(int maxPoints);
|
||||
|
||||
default int getMinY() {
|
||||
return getMinimumPoint().getY();
|
||||
}
|
||||
|
||||
default int getMaxY() {
|
||||
return getMaximumPoint().getY();
|
||||
}
|
||||
|
||||
default void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set) {
|
||||
int minSection = Math.max(0, getMinY() >> 4);
|
||||
int maxSection = Math.min(15, getMaxY() >> 4);
|
||||
for (int layer = minSection; layer <= maxSection; layer++) {
|
||||
if (!get.hasSection(layer) || !filter.appliesLayer(chunk, layer)) return;
|
||||
block = block.init(get, set, layer);
|
||||
block.filter(filter, this);
|
||||
}
|
||||
}
|
||||
|
||||
default void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set, final int minY, final int maxY) {
|
||||
int minSection = minY >> 4;
|
||||
int maxSection = maxY >> 4;
|
||||
int yStart = (minY & 15);
|
||||
int yEnd = (maxY & 15);
|
||||
if (minSection == maxSection) {
|
||||
filter(chunk, filter, block, get, set, minSection, yStart, yEnd);
|
||||
return;
|
||||
}
|
||||
if (yStart != 0) {
|
||||
filter(chunk, filter, block, get, set, minSection, yStart, 15);
|
||||
minSection++;
|
||||
}
|
||||
if (yEnd != 15) {
|
||||
filter(chunk, filter, block, get, set, minSection, 0, yEnd);
|
||||
maxSection--;
|
||||
}
|
||||
for (int layer = minSection; layer < maxSection; layer++) {
|
||||
filter(chunk, filter, block, get, set, layer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set, int layer) {
|
||||
if (!get.hasSection(layer) || !filter.appliesLayer(chunk, layer)) return;
|
||||
block = block.init(get, set, layer);
|
||||
block.filter(filter);
|
||||
}
|
||||
|
||||
default void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set, int layer, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
|
||||
if (!get.hasSection(layer) || !filter.appliesLayer(chunk, layer)) return;
|
||||
block = block.init(get, set, layer);
|
||||
block.filter(filter, minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
default void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set, int layer, int yStart, int yEnd) {
|
||||
if (!get.hasSection(layer) || !filter.appliesLayer(chunk, layer)) return;
|
||||
block = block.init(get, set, layer);
|
||||
block.filter(filter, yStart, yEnd);
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
@ -31,6 +28,9 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* An intersection of several other regions. Any location that is contained in one
|
||||
* of the child regions is considered as contained by this region.
|
||||
|
@ -1,191 +0,0 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.Identity;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Transforms another region according to a provided vector {@code Transform}.
|
||||
*
|
||||
* @see Transform
|
||||
*/
|
||||
public class TransformRegion extends AbstractRegion {
|
||||
|
||||
private final Region region;
|
||||
private Transform transform = new Identity();
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param region the region
|
||||
* @param transform the transform
|
||||
*/
|
||||
public TransformRegion(Region region, Transform transform) {
|
||||
this(null, region, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param world the world, which may be null
|
||||
* @param region the region
|
||||
* @param transform the transform
|
||||
*/
|
||||
public TransformRegion(@Nullable World world, Region region, Transform transform) {
|
||||
super(world);
|
||||
checkNotNull(region);
|
||||
checkNotNull(transform);
|
||||
this.region = region;
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the untransformed, base region.
|
||||
*
|
||||
* @return the base region
|
||||
*/
|
||||
public Region getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transform that is applied.
|
||||
*
|
||||
* @return the transform
|
||||
*/
|
||||
public Transform getTransform() {
|
||||
return transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transform that is applied.
|
||||
*
|
||||
* @param transform the transform
|
||||
*/
|
||||
public void setTransform(Transform transform) {
|
||||
checkNotNull(transform);
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return transform.apply(region.getMinimumPoint().toVector3()).toBlockPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return transform.apply(region.getMaximumPoint().toVector3()).toBlockPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return transform.apply(region.getCenter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArea() {
|
||||
return region.getArea(); // Cannot transform this
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return getMaximumPoint().subtract(getMinimumPoint()).getBlockX() + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return getMaximumPoint().subtract(getMinimumPoint()).getBlockY() + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return getMaximumPoint().subtract(getMinimumPoint()).getBlockZ() + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand(BlockVector3... changes) throws RegionOperationException {
|
||||
throw new RegionOperationException("Can't expand a TransformedRegion");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contract(BlockVector3... changes) throws RegionOperationException {
|
||||
throw new RegionOperationException("Can't contract a TransformedRegion");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shift(BlockVector3 change) throws RegionOperationException {
|
||||
throw new RegionOperationException("Can't change a TransformedRegion");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(BlockVector3 position) {
|
||||
return region.contains(transform.inverse().apply(position.toVector3()).toBlockPoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2> polygonize(int maxPoints) {
|
||||
List<BlockVector2> origPoints = region.polygonize(maxPoints);
|
||||
List<BlockVector2> transformedPoints = new ArrayList<>();
|
||||
for (BlockVector2 vector : origPoints) {
|
||||
transformedPoints.add(transform.apply(vector.toVector3(0)).toVector2().toBlockPoint());
|
||||
}
|
||||
return transformedPoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
final Iterator<BlockVector3> it = region.iterator();
|
||||
|
||||
return new Iterator<BlockVector3>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 next() {
|
||||
BlockVector3 next = it.next();
|
||||
if (next != null) {
|
||||
return transform.apply(next.toVector3()).toBlockPoint();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
it.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user