From de4dcc0dd5caf28b55474343fe5de870857be1e1 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Wed, 26 Jun 2019 20:22:21 +1000 Subject: [PATCH] idk, messing around with region filtering --- .../com/boydti/fawe/beta/CharFilterBlock.java | 100 +++++-------- .../boydti/fawe/beta/ChunkFilterBlock.java | 13 +- .../java/com/boydti/fawe/beta/IBlocks.java | 2 +- .../java/com/boydti/fawe/beta/IChunk.java | 2 +- .../java/com/boydti/fawe/beta/IChunkSet.java | 4 +- .../com/boydti/fawe/beta/NorthVector.java | 1 - .../boydti/fawe/beta/SimpleFilterBlock.java | 8 -- .../beta/implementation/DelegateChunkSet.java | 113 +++++++++++++++ .../implementation/blocks/CharBlocks.java | 14 +- .../implementation/blocks/CharGetBlocks.java | 6 +- .../implementation/blocks/CharSetBlocks.java | 3 +- .../blocks/RegionCharSetBlocks.java | 77 ++++++++++ .../implementation/holder/ChunkHolder.java | 40 ++---- .../worldedit/function/RegionFunction.java | 1 - .../sk89q/worldedit/regions/CuboidRegion.java | 88 ++++++------ .../worldedit/regions/CylinderRegion.java | 47 ++++-- .../worldedit/regions/EllipsoidRegion.java | 135 ++++++++++++++++-- .../com/sk89q/worldedit/regions/Region.java | 94 ++++++++---- .../worldedit/regions/RegionIntersection.java | 11 +- .../session/request/RequestSelection.java | 5 - 20 files changed, 542 insertions(+), 222 deletions(-) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/DelegateChunkSet.java create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/RegionCharSetBlocks.java 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 15d16d5ff..a4e2bbc71 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 @@ -16,7 +16,6 @@ import javax.annotation.Nullable; import static com.sk89q.worldedit.world.block.BlockTypes.states; public class CharFilterBlock extends ChunkFilterBlock { private CharGetBlocks get; - private IChunkSet set; private char[] getArr; @@ -43,7 +42,7 @@ public class CharFilterBlock extends ChunkFilterBlock { public void flood(final IChunkGet iget, final IChunkSet iset, final int layer, Flood flood, FilterBlockMask mask) { final int maxDepth = flood.getMaxDepth(); final boolean checkDepth = maxDepth < Character.MAX_VALUE; - if (init(iget, iset, layer)) { + if (init(iget, iset, layer) != null) { while ((index = flood.poll()) != -1) { x = index & 15; z = (index >> 4) & 15; @@ -62,10 +61,11 @@ public class CharFilterBlock extends ChunkFilterBlock { } } - private final boolean init(final IChunkGet iget, final IChunkSet iset, final int layer) { + @Override + public final ChunkFilterBlock init(final IChunkGet iget, final IChunkSet iset, final int layer) { this.layer = layer; final CharGetBlocks get = (CharGetBlocks) iget; - if (!get.hasSection(layer)) return false; + if (!get.hasSection(layer)) return null; this.set = iset; getArr = get.sections[layer].get(get, layer); if (set.hasSection(layer)) { @@ -76,29 +76,44 @@ public class CharFilterBlock extends ChunkFilterBlock { setArr = null; } this.yy = layer << 4; - return true; + return this; } @Override - public final void filter(final IChunkGet iget, final IChunkSet iset, final int layer, final Filter filter, final @Nullable Region region, BlockVector3 min, BlockVector3 max) { - if (init(iget, iset, layer)) { - 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); + public void filter(Filter filter, int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + this.index = x | (z << 4) | (y << 8); + filter.applyBlock(this); + } + + @Override + public void filter(Filter filter, int yStart, int yEnd) { + for (y = yStart, index = (yStart << 8); y < yEnd; y++) { + for (z = 0; z < 16; z++) { + for (x = 0; x < 16; x++, index++) { + filter.applyBlock(this); } } } } - private void iterate(final Region region, final Filter filter) { + @Override + public void filter(Filter filter, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { + int yis = (minY << 8); + int zis = (minZ << 4); + for (y = minY, index = yis; y <= maxY; y++) { + for (z = minZ, index += zis; z <= maxZ; z++) { + for (x = minX, index += minX; x <= maxX; x++, index++) { + filter.applyBlock(this); + } + } + } + } + + @Override + public final void filter(final Filter filter, final Region region) { for (y = 0, index = 0; y < 16; y++) { int absY = yy + y; for (z = 0; z < 16; z++) { @@ -113,51 +128,8 @@ public class CharFilterBlock extends ChunkFilterBlock { } } - 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) { + @Override + public final void filter(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/ChunkFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/ChunkFilterBlock.java index 8dd9f95f8..bc1957f51 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/ChunkFilterBlock.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/ChunkFilterBlock.java @@ -13,7 +13,18 @@ public abstract class ChunkFilterBlock extends SimpleFilterBlock { public abstract ChunkFilterBlock init(int X, int Z, IChunkGet chunk); + public abstract ChunkFilterBlock init(final IChunkGet iget, final IChunkSet iset, final int layer); + public abstract void flood(final IChunkGet iget, final IChunkSet iset, final int layer, Flood flood, FilterBlockMask mask); - public abstract void filter(IChunkGet get, IChunkSet set, int layer, Filter filter, @Nullable Region region, BlockVector3 min, BlockVector3 max); + + public abstract void filter(Filter filter, int x, int y, int z); + + public abstract void filter(Filter filter, int minX, int minY, int minZ, int maxX, int maxY, int maxZ); + + public abstract void filter(Filter filter); + + public abstract void filter(Filter filter, int yStart, int yEnd); + + public abstract void filter(final Filter filter, final Region region); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java index 0a63725e1..fce4a574d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java @@ -6,5 +6,5 @@ package com.boydti.fawe.beta; public interface IBlocks extends Trimable { boolean hasSection(int layer); - void reset(); + IChunkSet reset(); } \ No newline at end of file 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 ed8c080b0..26be59e53 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 @@ -71,7 +71,7 @@ public interface IChunk> extends Trimable, Callable { * @param unitialized a mutable block vector (buffer) * @param unitialized2 a mutable block vector (buffer) */ - void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, MutableBlockVector3 unitialized, MutableBlockVector3 unitialized2); + void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region); void flood(Flood flood, FilterBlockMask mask, ChunkFilterBlock block); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java index bef4af0bf..35efd352a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java @@ -8,8 +8,6 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -43,7 +41,7 @@ public interface IChunkSet extends IBlocks, OutputExtent { Set getEntityRemoves(); @Override - void reset(); + IChunkSet reset(); @Nullable @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/NorthVector.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/NorthVector.java index c0b4c8e5e..2b3581395 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/NorthVector.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/NorthVector.java @@ -3,7 +3,6 @@ package com.boydti.fawe.beta; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/SimpleFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/SimpleFilterBlock.java index 99ec8e2e6..b8d865aec 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/SimpleFilterBlock.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/SimpleFilterBlock.java @@ -1,14 +1,6 @@ package com.boydti.fawe.beta; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.Extent; -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; - -import javax.annotation.Nullable; public abstract class SimpleFilterBlock extends FilterBlock { private final Extent extent; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/DelegateChunkSet.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/DelegateChunkSet.java new file mode 100644 index 000000000..6b224de56 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/DelegateChunkSet.java @@ -0,0 +1,113 @@ +package com.boydti.fawe.beta.implementation; + +import com.boydti.fawe.beta.IChunkSet; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; + +import javax.annotation.Nullable; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +public interface DelegateChunkSet extends IChunkSet { + IChunkSet getParent(); + + @Override + default boolean setBiome(int x, int y, int z, BiomeType biome) { + return getParent().setBiome(x, y, z, biome); + } + + @Override + default boolean setBlock(int x, int y, int z, BlockStateHolder holder) { + return getParent().setBlock(x, y, z, holder); + } + + @Override + default boolean isEmpty() { + return getParent().isEmpty(); + } + + @Override + default void setTile(int x, int y, int z, CompoundTag tile) { + getParent().setTile(x, y, z, tile); + } + + @Override + default void setEntity(CompoundTag tag) { + getParent().setEntity(tag); + } + + @Override + default void removeEntity(UUID uuid) { + getParent().removeEntity(uuid); + } + + @Override + default BlockState getBlock(int x, int y, int z) { + return getParent().getBlock(x, y, z); + } + + @Override + default char[] getArray(int layer) { + return getParent().getArray(layer); + } + + @Override + default BiomeType[] getBiomes() { + return getParent().getBiomes(); + } + + @Override + default Map getTiles() { + return getParent().getTiles(); + } + + @Override + default Set getEntities() { + return getParent().getEntities(); + } + + @Override + default Set getEntityRemoves() { + return getParent().getEntityRemoves(); + } + + @Override + default IChunkSet reset() { + IChunkSet parent = getParent(); + parent.reset(); + return parent; + } + + @Override + @Nullable + default Operation commit() { + return getParent().commit(); + } + + @Override + default boolean hasSection(int layer) { + return getParent().hasSection(layer); + } + + @Override + default boolean trim(boolean aggressive) { + return getParent().trim(aggressive); + } + + @Override + default > boolean setBlock(BlockVector3 position, T block) throws WorldEditException { + return getParent().setBlock(position, block); + } + + @Override + default boolean setBiome(BlockVector2 position, BiomeType biome) { + return getParent().setBiome(position, biome); + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java index 66cb7b74a..0b94d17b3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java @@ -1,6 +1,7 @@ package com.boydti.fawe.beta.implementation.blocks; import com.boydti.fawe.beta.IBlocks; +import com.boydti.fawe.beta.IChunkSet; public class CharBlocks implements IBlocks { public final char[][] blocks; @@ -9,14 +10,14 @@ public class CharBlocks implements IBlocks { public CharBlocks() { blocks = new char[16][]; sections = new Section[16]; - for (int i = 0; i < 16; i++) sections[i] = NULL; + for (int i = 0; i < 16; i++) sections[i] = EMPTY; } @Override public boolean trim(final boolean aggressive) { boolean result = true; for (int i = 0; i < 16; i++) { - if (sections[i] == NULL) { + if (sections[i] == EMPTY) { blocks[i] = null; } else { result = false; @@ -26,12 +27,13 @@ public class CharBlocks implements IBlocks { } @Override - public void reset() { - for (int i = 0; i < 16; i++) sections[i] = NULL; + public IChunkSet reset() { + for (int i = 0; i < 16; i++) sections[i] = EMPTY; + return null; } public void reset(final int layer) { - sections[layer] = NULL; + sections[layer] = EMPTY; } public char[] load(final int layer) { @@ -84,7 +86,7 @@ public class CharBlocks implements IBlocks { } } - public static final Section NULL = new Section() { + public static final Section EMPTY = new Section() { @Override public final char[] get(final CharBlocks blocks, final int layer) { blocks.sections[layer] = FULL; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java index 467d78ee8..7c5dcf613 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java @@ -1,6 +1,7 @@ package com.boydti.fawe.beta.implementation.blocks; import com.boydti.fawe.beta.IChunkGet; +import com.boydti.fawe.beta.IChunkSet; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; @@ -19,14 +20,15 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { @Override public boolean trim(final boolean aggressive) { for (int i = 0; i < 16; i++) { - sections[i] = NULL; + sections[i] = EMPTY; blocks[i] = null; } return true; } @Override - public void reset() { + public IChunkSet reset() { super.reset(); + return null; } } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java index 883fe34a9..82d13aa0e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java @@ -102,11 +102,12 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { } @Override - public void reset() { + public IChunkSet reset() { biomes = null; tiles = null; entities = null; entityRemoves = null; super.reset(); + return null; } } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/RegionCharSetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/RegionCharSetBlocks.java new file mode 100644 index 000000000..caba79543 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/RegionCharSetBlocks.java @@ -0,0 +1,77 @@ +package com.boydti.fawe.beta.implementation.blocks; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.beta.IChunkSet; +import com.boydti.fawe.beta.implementation.DelegateChunkSet; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockStateHolder; + +public class RegionCharSetBlocks implements DelegateChunkSet { + private final Region region; + private final CharSetBlocks parent; + private final int X, Z; + + public RegionCharSetBlocks(Region region, int X, int Z, CharSetBlocks parent) { + this.region = region; + this.parent = parent; + this.X = X; + this.Z = Z; + } + + @Override + public CharSetBlocks getParent() { + return parent; + } + + public Region getRegion() { + return region; + } + + @Override + public boolean setBiome(int x, int y, int z, BiomeType biome) { + if (region.contains(x, y, z)) { + return parent.setBiome(x, y, z, biome); + } + return false; + } + + public static final CharBlocks.Section EMPTY_REGION = new CharBlocks.Section() { + @Override + public final char[] get(final CharBlocks blocks, final int layer) { + RegionCharSetBlocks checked = (RegionCharSetBlocks) blocks; + Region region = checked.getRegion(); + + blocks.sections[layer] = FULL; + char[] arr = blocks.blocks[layer]; + if (arr == null) { + arr = blocks.blocks[layer] = blocks.load(layer); + } else { + blocks.blocks[layer] = blocks.load(layer, arr); + } + return arr; + } + }; + + public static final CharBlocks.Section NULL = new CharBlocks.Section() { + @Override + public final char[] get(final CharBlocks blocks, final int layer) { + return FaweCache.EMPTY_CHAR_4096; + } + }; + + // EMPTY_CHAR_4096 + + @Override + public boolean setBlock(final int x, final int y, final int z, final BlockStateHolder holder) { + + } + + @Override + public void setTile(final int x, final int y, final int z, final CompoundTag tile) { + if (region.contains(x, y, z)) { + super.setTile(x, y, z, tile); + } + } +} 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 b1336a480..3f8f43471 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 @@ -2,16 +2,15 @@ package com.boydti.fawe.beta.implementation.holder; import com.boydti.fawe.beta.ChunkFilterBlock; import com.boydti.fawe.beta.Filter; -import com.boydti.fawe.beta.FilterBlock; import com.boydti.fawe.beta.FilterBlockMask; import com.boydti.fawe.beta.Flood; -import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks; import com.boydti.fawe.beta.IChunk; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkSet; +import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent; import com.boydti.fawe.beta.implementation.WorldChunkCache; +import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks; import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.regions.Region; @@ -47,39 +46,20 @@ public abstract class ChunkHolder implements IChunk, Supplier { } @Override - public void filterBlocks(final Filter filter, ChunkFilterBlock block, @Nullable Region region, @Nullable final MutableBlockVector3 min, @Nullable final MutableBlockVector3 max) { + public void filterBlocks(final Filter filter, ChunkFilterBlock block, @Nullable Region region) { final IChunkGet get = getOrCreateGet(); final IChunkSet set = getOrCreateSet(); try { if (region != null) { - switch (region.getChunkBounds(X, Z, min, max)) { - case 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; - 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; - } + region.filter(this, filter, block, get, set); + } else { + block = block.init(X, Z, get); + for (int layer = 0; layer < 16; layer++) { + if (!get.hasSection(layer) || !filter.appliesLayer(this, layer)) continue; + block.init(get, set, layer); + block.filter(filter); } } - - 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); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/RegionFunction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/RegionFunction.java index 332565e35..25f5f22d7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/RegionFunction.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/RegionFunction.java @@ -35,5 +35,4 @@ public interface RegionFunction { * @throws WorldEditException thrown on an error */ boolean apply(BlockVector3 position) throws WorldEditException; - } 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 913285e52..5b58b217e 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 @@ -19,29 +19,27 @@ 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 static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import com.boydti.fawe.object.collection.BlockVectorSet; -import com.boydti.fawe.object.collection.LocalBlockVectorSet; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.math.MutableBlockVector2; +import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.storage.ChunkStore; import java.util.AbstractSet; -import java.util.HashSet; import java.util.Iterator; import java.util.NoSuchElementException; 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. @@ -400,13 +398,7 @@ 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); - } @Override public Iterator iterator() { if (Settings.IMP.HISTORY.COMPRESSION_LEVEL >= 9 || useOldIterator) { @@ -629,35 +621,49 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { } @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 <= Z) { - int maxChunkZ = maxZ >> 4; - if (maxChunkZ >= Z) { - int cx1 = X << 4; - int cx2 = cx1 + 15; - int cz1 = Z << 4; - int cz2 = cz1 + 15; + public int getMinY() { + return minY; + } - int bx = Math.max(cx1, minX); - int bz = Math.max(cz1, minZ); - int tx = Math.min(cx2, maxX); - int tz = Math.min(cz2, maxZ); + @Override + public int getMaxY() { + return maxY; + } - 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; - } - } - } + @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); } - return NONE; } } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java index 90892ed12..a2741b061 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java @@ -21,6 +21,11 @@ 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.BlockVector3; import com.sk89q.worldedit.math.BlockVector2; @@ -290,25 +295,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; } - 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. * @@ -363,6 +365,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 @@ -381,4 +393,17 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { int maxY = extent.getMaximumPoint().getBlockY(); 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); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java index 0c0be6781..bf5c4d8e3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java @@ -20,6 +20,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.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; @@ -215,19 +220,19 @@ public class EllipsoidRegion extends AbstractRegion { return chunks; } - @Override - public boolean contains(BlockVector3 position) { - int cx = position.getBlockX() - center.getBlockX(); + @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 = 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 cy = y - center.getBlockY(); int cy2 = cy * cy; if (radiusSqr.getBlockY() < 255 && cy2 > radiusSqr.getBlockY()) { return false; @@ -235,10 +240,30 @@ public class EllipsoidRegion extends AbstractRegion { if (sphere) { return cx2 + cy2 + cz2 <= radiusLengthSqr; } - double cxd = cx * inverseRadius.getX(); - double cyd = cy * inverseRadius.getY(); - double czd = cz * inverseRadius.getZ(); - return cxd * cxd + cyd * cyd + czd * czd <= 1; + double cxd = cx2 * inverseRadius.getX(); + double cyd = cy2 * inverseRadius.getY(); + double czd = cz2 * inverseRadius.getZ(); + return cxd + cyd + czd <= 1; + } + + @Override + public boolean contains(int x, 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; + } + if (sphere) { + return cx2 + cz2 <= radiusLengthSqr; + } + double cxd = cx2 * inverseRadius.getX(); + double czd = cz2 * inverseRadius.getZ(); + return cxd + czd <= 1; } /** @@ -260,4 +285,96 @@ public class EllipsoidRegion extends AbstractRegion { public EllipsoidRegion clone() { return (EllipsoidRegion) super.clone(); } + + @Override + public void filter(IChunk chunk, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set) { + int bx = chunk.getX() << 4; + int bz = chunk.getZ() << 4; + int tx = bx + 15; + int tz = bz + 15; + int cx1 = bx - center.getBlockX(); + int cx2 = tx - center.getBlockX(); + 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 - center.getBlockZ(); + int cz2 = tz - center.getBlockZ(); + 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) { + if (cxMin2 + czMin2 >= radiusLengthSqr) { + return; + } + int diffY2 = radiusLengthSqr - cxMax2 - czMax2; + if (diffY2 > 0) { + diffy2 + } + + + + } else { + if (cxMin2 * inverseRadius.getX() + czMin2 * inverseRadius.getZ() > 1) { + return; + } + partial = cxMax2 * inverseRadius.getX() + czMax2 * inverseRadius.getZ() > 1; + } + if (partial) { + + } else { + // get min y and max y + for (int layer = 0; layer < 16; layer++) { + // if contains all + { + filter(chunk, ) + } + } + } + + + int cy1 = 0 - center.getBlockY(); + int cy2 = 255 - center.getBlockY(); + int cyMax, cyMin; + if (cy1 < cy2) { + cyMin = cy1; + cyMax = cy2; + } else { + cyMin = cy2; + cyMax = cy1; + } + int cyMin2 = cyMin * cyMin; + int cyMax2 = cyMax * cyMax; + + boolean containsMin = contains(bx, bz); + boolean containsMax = contains(tx, tz); + if (containsMin && containsMax) { + // set all + return; + } + + + for (int layer = 0; layer < 16; layer++) { + if (contains()) + } + TODO optimize; + int minY = getMinY(); + int maxY = getMaxY(); + contains() + } } 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 a90bea7a8..bdecfc4de 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 @@ -19,6 +19,12 @@ 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; @@ -26,12 +32,10 @@ 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; -import static com.sk89q.worldedit.regions.Region.Contains.CHECKED; -import static com.sk89q.worldedit.regions.Region.Contains.NONE; - /** * Represents a physical shape. */ @@ -137,7 +141,9 @@ public interface Region extends Iterable, 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. @@ -183,32 +189,62 @@ public interface Region extends Iterable, Cloneable { */ 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; + default int getMinY() { + return getMinimumPoint().getY(); } - enum Contains { - FULL, - PARTIAL, - CHECKED, - NONE; + 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); } } 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 161852248..cc1dbd954 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 @@ -19,16 +19,8 @@ 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; @@ -36,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. 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 3766676fd..7645154f8 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 @@ -148,11 +148,6 @@ 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();