From 7c174beaeeb2a9b9a880995aca0bed30735d6414 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Sun, 5 May 2019 03:58:26 +1000 Subject: [PATCH] Region filter --- .../fawe/bukkit/beta/BukkitChunkHolder.java | 7 - .../com/boydti/fawe/beta/CharFilterBlock.java | 78 ++++++- .../java/com/boydti/fawe/beta/Filter.java | 8 +- .../com/boydti/fawe/beta/FilterBlock.java | 3 +- .../java/com/boydti/fawe/beta/IChunk.java | 21 +- .../com/boydti/fawe/beta/IDelegateChunk.java | 12 +- .../com/boydti/fawe/beta/IDelegateFilter.java | 28 +-- .../com/boydti/fawe/beta/RegionFilter.java | 37 ---- .../beta/implementation/QueueHandler.java | 10 +- .../implementation/holder/ChunkHolder.java | 44 +++- .../sk89q/worldedit/regions/CuboidRegion.java | 32 +++ .../com/sk89q/worldedit/regions/Region.java | 33 +++ .../worldedit/regions/RegionIntersection.java | 5 + .../worldedit/regions/TransformRegion.java | 191 ------------------ .../session/request/RequestSelection.java | 6 + 15 files changed, 232 insertions(+), 283 deletions(-) delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/RegionFilter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java index 7abe76c21..7739a66b7 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java @@ -349,11 +349,4 @@ public class BukkitChunkHolder> extends ChunkHolder { return null; } } - - @Override - public void set(final Filter filter) { - // for each block - // filter.applyBlock(block) - throw new UnsupportedOperationException("Not implemented"); - } } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java index 8d767b49e..42a90e24c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java @@ -2,6 +2,8 @@ package com.boydti.fawe.beta; import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; @@ -40,7 +42,7 @@ public class CharFilterBlock implements FilterBlock { } @Override - public final void filter(final IGetBlocks iget, final ISetBlocks iset, final int layer, final Filter filter) { + public final void filter(final IGetBlocks iget, final ISetBlocks iset, final int layer, final Filter filter, final @Nullable Region region, BlockVector3 min, BlockVector3 max) { this.layer = layer; final CharGetBlocks get = (CharGetBlocks) iget; if (!get.hasSection(layer)) return; @@ -54,7 +56,81 @@ public class CharFilterBlock implements FilterBlock { setArr = null; } this.yy = layer << 4; + if (region == null) { + if (min != null && max != null) { + iterate(min, max, layer, filter); + } else { + iterate(filter); + } + } else { + if (min != null && max != null) { + iterate(region, min, max, layer, filter); + } else { + iterate(region, filter); + } + } + } + private void iterate(final Region region, final Filter filter) { + for (y = 0, index = 0; y < 16; y++) { + int absY = yy + y; + for (z = 0; z < 16; z++) { + int absZ = zz + z; + for (x = 0; x < 16; x++, index++) { + int absX = xx + x; + if (region.contains(absX, absY, absZ)) { + filter.applyBlock(this); + } + } + } + } + } + + private void iterate(final Region region, BlockVector3 min, BlockVector3 max, int layer, final Filter filter) { + int by = Math.max(min.getY(), layer << 4) & 15; + int ty = Math.min(max.getY(), 15 + (layer << 4)) & 15; + int bx = min.getX(); + int bz = min.getZ(); + int tx = max.getX(); + int tz = max.getZ(); + for (y = by; y <= ty; y++) { + int yIndex = (y << 8); + int absY = yy + y; + for (z = bz; z <= tz; z++) { + int zIndex = yIndex + ((z) << 4); + int absZ = zz + z; + for (x = bx; x <= tx; x++) { + index = zIndex + x; + int absX = xx + x; + if (region.contains(absX, absY, absZ)) { + filter.applyBlock(this); + } + + } + } + } + } + + private void iterate(BlockVector3 min, BlockVector3 max, int layer, final Filter filter) { + int by = Math.max(min.getY(), layer << 4) & 15; + int ty = Math.min(max.getY(), 15 + (layer << 4)) & 15; + int bx = min.getX(); + int bz = min.getZ(); + int tx = max.getX(); + int tz = max.getZ(); + for (y = by; y <= ty; y++) { + int yIndex = (y << 8); + for (z = bz; z <= tz; z++) { + int zIndex = yIndex + ((z) << 4); + for (x = bx; x <= tx; x++) { + index = zIndex + x; + filter.applyBlock(this); + } + } + } + } + + private final void iterate(final Filter filter) { for (y = 0, index = 0; y < 16; y++) { for (z = 0; z < 16; z++) { for (x = 0; x < 16; x++, index++) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java index ba55e3ef9..2f19852c3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java @@ -16,8 +16,8 @@ public interface Filter { * @param cz * @return */ - default Filter appliesChunk(final int cx, final int cz) { - return this; + default boolean appliesChunk(final int cx, final int cz) { + return true; } /** @@ -32,8 +32,8 @@ public interface Filter { return chunk; } - default Filter appliesLayer(IChunk chunk, int layer) { - return this; + default boolean appliesLayer(IChunk chunk, int layer) { + return true; } /** diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java index c2e6508b3..96a06562e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java @@ -1,6 +1,7 @@ package com.boydti.fawe.beta; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -12,7 +13,7 @@ public interface FilterBlock { FilterBlock init(int X, int Z, IGetBlocks chunk); - void filter(IGetBlocks get, ISetBlocks set, int layer, Filter filter, @Nullable Region region); + void filter(IGetBlocks get, ISetBlocks set, int layer, Filter filter, @Nullable Region region, BlockVector3 min, BlockVector3 max); void setOrdinal(int ordinal); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java index 827bc8c7a..dbc45d124 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java @@ -1,10 +1,13 @@ package com.boydti.fawe.beta; +import com.sk89q.worldedit.math.MutableBlockVector3; +import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import javax.annotation.Nullable; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -61,23 +64,25 @@ public interface IChunk> extends Trimable, Callable { return; } + /** + * Filter + * @param filter the filter + * @param block The filter block + * @param region The region allowed to filter (may be null) + * @param unitialized a mutable block vector (buffer) + * @param unitialized2 a mutable block vector (buffer) + */ + void filter(Filter filter, FilterBlock block, @Nullable Region region, MutableBlockVector3 unitialized, MutableBlockVector3 unitialized2); + /* set - queues a change */ boolean setBiome(int x, int y, int z, BiomeType biome); boolean setBlock(int x, int y, int z, BlockStateHolder block); - /** - * Set using the filter - * @param filter - */ - void set(Filter filter); - /* get - from the world */ BiomeType getBiome(int x, int z); BlockState getBlock(int x, int y, int z); BaseBlock getFullBlock(int x, int y, int z); - - void filter(Filter filter, FilterBlock mutable); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateChunk.java index 8d57af1be..0a21e1c1a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateChunk.java @@ -1,10 +1,13 @@ package com.boydti.fawe.beta; +import com.sk89q.worldedit.math.MutableBlockVector3; +import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import javax.annotation.Nullable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -80,8 +83,8 @@ public interface IDelegateChunk extends IChunk { } @Override - default void filter(final Filter filter, final FilterBlock mutable) { - getParent().filter(filter, mutable); + default void filter(Filter filter, FilterBlock block, @Nullable Region region, MutableBlockVector3 unitialized, MutableBlockVector3 unitialized2) { + getParent().filter(filter, block, region, unitialized, unitialized2); } @Override @@ -98,9 +101,4 @@ public interface IDelegateChunk extends IChunk { } return null; } - - @Override - default void set(final Filter filter) { - getParent().set(filter); - } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java index 9f8274ef0..c954b91d4 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java @@ -1,33 +1,25 @@ package com.boydti.fawe.beta; +import com.sk89q.worldedit.regions.Region; + +import javax.annotation.Nullable; + public interface IDelegateFilter extends Filter { Filter getParent(); @Override - default Filter appliesChunk(int cx, int cz) { - Filter copy = getParent().appliesChunk(cx, cz); - if (copy == null) return null; - if (copy != getParent()) { - return newInstance(copy); - } else { - return this; - } + default boolean appliesChunk(int cx, int cz) { + return getParent().appliesChunk(cx, cz); } @Override - default IChunk applyChunk(IChunk chunk) { - return getParent().applyChunk(chunk); + default IChunk applyChunk(IChunk chunk, @Nullable Region region) { + return getParent().applyChunk(chunk, region); } @Override - default Filter appliesLayer(IChunk chunk, int layer) { - Filter copy = getParent().appliesLayer(chunk, layer); - if (copy == null) return null; - if (copy != getParent()) { - return newInstance(copy); - } else { - return this; - } + default boolean appliesLayer(IChunk chunk, int layer) { + return getParent().appliesLayer(chunk, layer); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/RegionFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/RegionFilter.java deleted file mode 100644 index 791e040d6..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/RegionFilter.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.boydti.fawe.beta; - -import com.sk89q.worldedit.regions.Region; - -public class RegionFilter extends DelegateFilter { - private final Region region; - - public RegionFilter(Filter parent, Region region) { - super(parent); - this.region = region; - } - - @Override - public Filter appliesChunk(int cx, int cz) { - return getParent().appliesChunk(cx, cz); - } - - @Override - public Filter appliesLayer(IChunk chunk, int layer) { - return getParent().appliesLayer(chunk, layer); - } - - @Override - public void applyBlock(FilterBlock block) { - getParent().applyBlock(block); - } - - @Override - public void finishChunk(IChunk chunk) { - getParent().finishChunk(chunk); - } - - @Override - public Filter newInstance(Filter other) { - return new RegionFilter(other, region); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java index 26e7bf898..a7ebe3676 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java @@ -13,6 +13,7 @@ import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.wrappers.WorldWrapper; import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; @@ -155,6 +156,9 @@ public abstract class QueueHandler implements Trimable, Runnable { tasks[i] = forkJoinPoolPrimary.submit(new Runnable() { @Override public void run() { + MutableBlockVector3 mbv1 = new MutableBlockVector3(); + MutableBlockVector3 mbv2 = new MutableBlockVector3(); + final Filter newFilter = filter.fork(); // Create a chunk that we will reuse/reset for each operation final IQueueExtent queue = getQueue(world); @@ -162,7 +166,7 @@ public abstract class QueueHandler implements Trimable, Runnable { FilterBlock block = null; while (true) { - // Get the next chunk pos + // Get the next chunk posWeakChunk final int X, Z; synchronized (chunksIter) { if (!chunksIter.hasNext()) break; @@ -177,12 +181,12 @@ public abstract class QueueHandler implements Trimable, Runnable { // Initialize chunk.init(queue, X, Z); - chunk = newFilter.applyChunk(chunk); + chunk = newFilter.applyChunk(chunk, region); if (chunk == null) continue; if (block == null) block = queue.initFilterBlock(); - chunk.filter(newFilter, block); + chunk.filter(newFilter, block, region, mbv1, mbv2); queue.submit(chunk); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java index 878f3c039..e2284fe51 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java @@ -10,11 +10,14 @@ import com.boydti.fawe.beta.ISetBlocks; import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent; import com.boydti.fawe.beta.implementation.WorldChunkCache; import com.boydti.fawe.util.MathMan; +import com.sk89q.worldedit.math.MutableBlockVector3; +import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import javax.annotation.Nullable; import java.util.function.Supplier; /** @@ -36,15 +39,44 @@ public abstract class ChunkHolder implements IChunk, Supplier { } @Override - public void filter(final Filter filter, FilterBlock block) { + public void filter(final Filter filter, FilterBlock block, @Nullable Region region, final MutableBlockVector3 min, final MutableBlockVector3 max) { final IGetBlocks get = getOrCreateGet(); final ISetBlocks set = getOrCreateSet(); - block = block.init(X, Z, get); - for (int layer = 0; layer < 16; layer++) { - if (!get.hasSection(layer) || !filter.appliesLayer(this, layer)) continue; - block.filter(get, set, layer, filter); + try { + if (region != null) { + switch (region.getChunkBounds(X, Z, min, max)) { + case NONE: + System.out.println("NONE"); + return; + case FULL: + if (min.getY() == 0 && max.getY() == 255) { + break; + } + case PARTIAL: + region = null; + case CHECKED: + default: { + int minLayer = min.getY() >> 4; + int maxLayer = max.getY() >> 4; + System.out.println("Layers " + minLayer + " | " + maxLayer); + block = block.init(X, Z, get); + for (int layer = minLayer; layer < maxLayer; layer++) { + if (!get.hasSection(layer) || !filter.appliesLayer(this, layer)) continue; + block.filter(get, set, layer, filter, region, min, max); + } + return; + } + } + } + + block = block.init(X, Z, get); + for (int layer = 0; layer < 16; layer++) { + if (!get.hasSection(layer) || !filter.appliesLayer(this, layer)) continue; + block.filter(get, set, layer, filter, region, null, null); + } + } finally { + filter.finishChunk(this); } - filter.finishChunk(this); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java index 5d6da1301..34a42ec4d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java @@ -41,6 +41,7 @@ import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.regions.Region.Contains.*; /** * An axis-aligned cuboid. It can be defined using two corners of the cuboid. @@ -627,5 +628,36 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { return new CuboidRegion(origin.subtract(size), origin.add(size)); } + @Override + public Contains getChunkBounds(int X, int Z, MutableBlockVector3 min, MutableBlockVector3 max) { + int minChunkX = minX >> 4; + if (minChunkX <= X) { + int maxChunkX = maxX >> 4; + if (maxChunkX >= X) { + int minChunkZ = minZ >> 4; + if (minChunkZ <= X) { + int maxChunkZ = maxZ >> 4; + if (maxChunkZ >= Z) { + int cx1 = X << 4; + int cx2 = cx1 + 15; + int cz1 = Z << 4; + int cz2 = cz1 + 15; + int bx = Math.max(cx1, minX); + int bz = Math.max(cz1, minZ); + int tx = Math.min(cx2, maxX); + int tz = Math.min(cz2, maxZ); + + min.setComponents(bx & 15, minY, bz & 15); + max.setComponents(tx & 15, maxY, tz & 15); + if (min.getX() == 0 && min.getZ() == 0 && max.getX() == 15 && max.getZ() == 15) { + return FULL; + } + return PARTIAL; + } + } + } + } + return NONE; + } } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java index 8c4c75a48..a90bea7a8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.regions; 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; @@ -28,6 +29,9 @@ import javax.annotation.Nullable; import java.util.List; import java.util.Set; +import static com.sk89q.worldedit.regions.Region.Contains.CHECKED; +import static com.sk89q.worldedit.regions.Region.Contains.NONE; + /** * Represents a physical shape. */ @@ -178,4 +182,33 @@ public interface Region extends Iterable, Cloneable { * @return the points. */ List polygonize(int maxPoints); + + default Contains getChunkBounds(int X, int Z, MutableBlockVector3 min, MutableBlockVector3 max) { + BlockVector3 pos1 = getMinimumPoint(); + BlockVector3 pos2 = getMaximumPoint(); + int cx1 = X << 4; + int cx2 = cx1 + 15; + int cz1 = Z << 4; + int cz2 = cz1 + 15; + + int bx = Math.max(cx1, pos1.getX()); + int bz = Math.max(cz1, pos1.getZ()); + int tx = Math.min(cx2, pos2.getX()); + int tz = Math.min(cz2, pos2.getZ()); + + min.setComponents(bx & 15, pos1.getY(), bz & 15); + max.setComponents(tx & 15, pos2.getY(), tz & 15); + + if (bx > cx2 || bz > cz2 || tx < cx1 || tz < cz1) { + return NONE; + } + return CHECKED; + } + + enum Contains { + FULL, + PARTIAL, + CHECKED, + NONE; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java index 9442deaca..161852248 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionIntersection.java @@ -21,9 +21,14 @@ package com.sk89q.worldedit.regions; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.regions.Region.Contains.CHECKED; +import static com.sk89q.worldedit.regions.Region.Contains.FULL; +import static com.sk89q.worldedit.regions.Region.Contains.NONE; +import static com.sk89q.worldedit.regions.Region.Contains.PARTIAL; import com.google.common.collect.Iterators; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.world.World; import java.util.ArrayList; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java deleted file mode 100644 index 911e40b8b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/TransformRegion.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * 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 . - */ - -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 polygonize(int maxPoints) { - List origPoints = region.polygonize(maxPoints); - List transformedPoints = new ArrayList<>(); - for (BlockVector2 vector : origPoints) { - transformedPoints.add(transform.apply(vector.toVector3(0)).toVector2().toBlockPoint()); - } - return transformedPoints; - } - - @Override - public Iterator iterator() { - final Iterator it = region.iterator(); - - return new Iterator() { - @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(); - } - }; - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestSelection.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestSelection.java index 9e37e4da0..3766676fd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestSelection.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestSelection.java @@ -23,6 +23,7 @@ import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; 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.regions.NullRegion; import com.sk89q.worldedit.regions.Region; @@ -147,6 +148,11 @@ public class RequestSelection implements Region { return getRegion().polygonize(maxPoints); } + @Override + public Contains getChunkBounds(int X, int Z, MutableBlockVector3 min, MutableBlockVector3 max) { + return getRegion().getChunkBounds(X, Z, min, max); + } + @Override public Iterator iterator() { return getRegion().iterator();