diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/AbstractFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/AbstractFilterBlock.java new file mode 100644 index 000000000..2f544a47d --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/AbstractFilterBlock.java @@ -0,0 +1,94 @@ +package com.boydti.fawe.beta; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.math.BlockVector3; +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; + +public abstract class AbstractFilterBlock extends FilterBlock { + + public abstract BaseBlock getFullBlock(); + public abstract void setFullBlock(BaseBlock block); + public abstract BlockVector3 getPosition(); + + @Override + public Extent getExtent() { + return this; + } + + @Override + public int getX() { + return getPosition().getX(); + } + + @Override + public int getY() { + return getPosition().getY(); + } + + @Override + public int getZ() { + return getPosition().getZ(); + } + + @Override + public int getOrdinal() { + return getBlock().getOrdinal(); + } + + @Override + public void setOrdinal(int ordinal) { + setBlock(BlockState.getFromOrdinal(ordinal)); + } + + @Override + public BlockState getBlock() { + return getFullBlock().toBlockState(); + } + + @Override + public void setBlock(BlockState state) { + setFullBlock(state.toBaseBlock(getBlock().getNbtData())); + } + + @Override + public CompoundTag getNbtData() { + return getFullBlock().getNbtData(); + } + + @Override + public void setNbtData(@Nullable CompoundTag nbtData) { + setFullBlock(getFullBlock().toBaseBlock(nbtData)); + } + + @Override + public BlockVector3 getMinimumPoint() { + return BlockVector3.at(getX(), getY(), getZ()); + } + + @Override + public BlockVector3 getMaximumPoint() { + return BlockVector3.at(getX(), getY(), getZ()); + } + + @Override + public > boolean setBlock(int x, int y, int z, T block) + throws WorldEditException { + if (x == this.getX() && y == this.getY() && z == this.getZ()) { + setFullBlock(block.toBaseBlock()); + return true; + } + return getExtent().setBlock(x,y, z, block); + } + + @Override + public boolean setBiome(int x, int y, int z, BiomeType biome) { + return getExtent().setBiome(x, y, z,biome); + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/AbstractSingleFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/AbstractSingleFilterBlock.java new file mode 100644 index 000000000..171cda55a --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/AbstractSingleFilterBlock.java @@ -0,0 +1,92 @@ +package com.boydti.fawe.beta; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.math.BlockVector3; +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; + +public abstract class AbstractSingleFilterBlock extends FilterBlock { + + private BaseBlock block; + + public AbstractSingleFilterBlock init(BaseBlock block) { + this.block = block; + return this; + } + + @Override + public Extent getExtent() { + return this; + } + + @Override + public int getOrdinal() { + return block.getOrdinal(); + } + + @Override + public void setOrdinal(int ordinal) { + setBlock(BlockState.getFromOrdinal(ordinal)); + } + + @Override + public BlockState getBlock() { + return block.toBlockState(); + } + + @Override + public void setBlock(BlockState state) { + setFullBlock(state.toBaseBlock(block.getNbtData())); + } + + @Override + public BaseBlock getFullBlock() { + return block; + } + + @Override + public void setFullBlock(BaseBlock block) { + this.block = block; + } + + @Override + public CompoundTag getNbtData() { + return block.getNbtData(); + } + + @Override + public void setNbtData(@Nullable CompoundTag nbtData) { + block = block.toBaseBlock(nbtData); + } + + @Override + public BlockVector3 getMinimumPoint() { + return BlockVector3.at(getX(), getY(), getZ()); + } + + @Override + public BlockVector3 getMaximumPoint() { + return BlockVector3.at(getX(), getY(), getZ()); + } + + @Override + public > boolean setBlock(int x, int y, int z, T block) + throws WorldEditException { + if (x == this.getX() && y == this.getY() && z == this.getZ()) { + setFullBlock(block.toBaseBlock()); + return true; + } + return getExtent().setBlock(x,y, z, block); + } + + @Override + public boolean setBiome(int x, int y, int z, BiomeType biome) { + return getExtent().setBiome(x, y, z,biome); + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/ExtentFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/ExtentFilterBlock.java new file mode 100644 index 000000000..b5cb81c07 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/ExtentFilterBlock.java @@ -0,0 +1,35 @@ +package com.boydti.fawe.beta; + +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BaseBlock; + +public class ExtentFilterBlock extends AbstractFilterBlock { + private final Extent extent; + private BlockVector3 pos; + + public ExtentFilterBlock(Extent extent) { + this.extent = extent; + this.pos = BlockVector3.ZERO; + } + + public ExtentFilterBlock init(BlockVector3 pos) { + this.pos = pos; + return this; + } + + @Override + public BaseBlock getFullBlock() { + return pos.getFullBlock(extent); + } + + @Override + public void setFullBlock(BaseBlock block) { + pos.setFullBlock(extent, block); + } + + @Override + public BlockVector3 getPosition() { + return pos; + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java index 11f358703..89eeb9d08 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java @@ -9,7 +9,9 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; +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; @@ -17,7 +19,9 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import javax.annotation.Nullable; import java.io.Flushable; +import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.concurrent.Future; /** @@ -188,4 +192,35 @@ public interface IQueueExtent extends Flushable, Trimable, Extent, IBatchProcess * @return true if this queue contains no elements */ boolean isEmpty(); + + default ChunkFilterBlock apply(ChunkFilterBlock block, Filter filter, Region region, int X, int Z) { + if (!filter.appliesChunk(X, Z)) { + return block; + } + IChunk chunk = this.getOrCreateChunk(X, Z); + // Initialize + chunk.init(this, X, Z); + + IChunk newChunk = filter.applyChunk(chunk, region); + if (newChunk != null) { + chunk = newChunk; + if (block == null) { + block = this.initFilterBlock(); + } + chunk.filterBlocks(filter, block, region); + } + this.submit(chunk); + return block; + } + + @Override + default T apply(Region region, T filter) { + final Set chunks = region.getChunks(); + ChunkFilterBlock block = null; + for (BlockVector2 chunk : chunks) { + block = apply(block, filter, region, chunk.getX(), chunk.getZ()); + } + flush(); + return filter; + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/SingleFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/SingleFilterBlock.java index 631e14357..225aa3453 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/SingleFilterBlock.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/SingleFilterBlock.java @@ -1,74 +1,19 @@ package com.boydti.fawe.beta; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.extent.Extent; -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.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import javax.annotation.Nullable; -public class SingleFilterBlock extends FilterBlock { +public class SingleFilterBlock extends AbstractSingleFilterBlock { - private BaseBlock block; private int x, y, z; public SingleFilterBlock init(int x, int y, int z, BaseBlock block) { this.x = x; this.y = y; this.z = z; - this.block = block; + super.init(block); return this; } - @Override - public Extent getExtent() { - return this; - } - - @Override - public int getOrdinal() { - return block.getOrdinal(); - } - - @Override - public void setOrdinal(int ordinal) { - setBlock(BlockState.getFromOrdinal(ordinal)); - } - - @Override - public BlockState getBlock() { - return block.toBlockState(); - } - - @Override - public void setBlock(BlockState state) { - setFullBlock(state.toBaseBlock(block.getNbtData())); - } - - @Override - public BaseBlock getFullBlock() { - return block; - } - - @Override - public void setFullBlock(BaseBlock block) { - this.block = block; - } - - @Override - public CompoundTag getNbtData() { - return block.getNbtData(); - } - - @Override - public void setNbtData(@Nullable CompoundTag nbtData) { - block = block.toBaseBlock(nbtData); - } - @Override public int getX() { return x; @@ -83,29 +28,4 @@ public class SingleFilterBlock extends FilterBlock { public int getZ() { return z; } - - @Override - public BlockVector3 getMinimumPoint() { - return BlockVector3.at(x, y, z); - } - - @Override - public BlockVector3 getMaximumPoint() { - return BlockVector3.at(x, y, z); - } - - @Override - public > boolean setBlock(int x, int y, int z, T block) - throws WorldEditException { - if (x == this.x && y == this.y && z == this.z) { - setFullBlock(block.toBaseBlock()); - return true; - } - return getExtent().setBlock(x,y, z, block); - } - - @Override - public boolean setBiome(int x, int y, int z, BiomeType biome) { - return getExtent().setBiome(x,y, z,biome); - } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/VectorSingleFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/VectorSingleFilterBlock.java new file mode 100644 index 000000000..0e293ebf9 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/VectorSingleFilterBlock.java @@ -0,0 +1,32 @@ +package com.boydti.fawe.beta; + +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BaseBlock; + +public class VectorSingleFilterBlock extends AbstractSingleFilterBlock { + private final BlockVector3 mutable; + + public VectorSingleFilterBlock(BlockVector3 mutable) { + this.mutable = mutable; + } + + public VectorSingleFilterBlock init(BaseBlock block) { + super.init(block); + return this; + } + + @Override + public int getX() { + return mutable.getX(); + } + + @Override + public int getY() { + return mutable.getY(); + } + + @Override + public int getZ() { + return mutable.getZ(); + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/ParallelQueueExtent.java index 8fe062908..abeacd6b8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/ParallelQueueExtent.java @@ -70,26 +70,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap return super.enableHistory(changeSet); } - private ChunkFilterBlock apply(ChunkFilterBlock block, Filter filter, IQueueExtent queue, Region region, int X, int Z) { - if (!filter.appliesChunk(X, Z)) { - return block; - } - IChunk chunk = queue.getOrCreateChunk(X, Z); - // Initialize - chunk.init(queue, X, Z); - - IChunk newChunk = filter.applyChunk(chunk, region); - if (newChunk != null) { - chunk = newChunk; - if (block == null) { - block = queue.initFilterBlock(); - } - chunk.filterBlocks(filter, block, region); - } - queue.submit(chunk); - return block; - } - + @Override public T apply(Region region, T filter) { // The chunks positions to iterate over final Set chunks = region.getChunks(); @@ -99,7 +80,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS); if (size <= 1) { BlockVector2 pos = chunksIter.next(); - apply(null, filter, getExtent(), region, pos.getX(), pos.getZ()); + getExtent().apply(null, filter, region, pos.getX(), pos.getZ()); } else { final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> { try { @@ -120,7 +101,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap X = pos.getX(); Z = pos.getZ(); } - block = apply(block, newFilter, queue, region, X, Z); + block = queue.apply(block, newFilter, region, X, Z); } queue.flush(); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/SchematicStreamer.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/SchematicStreamer.java index b94f414e2..f93593a06 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/SchematicStreamer.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/SchematicStreamer.java @@ -22,10 +22,12 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockID; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypeSwitch; @@ -159,13 +161,13 @@ public class SchematicStreamer extends NBTStreamer { if (id.isEmpty()) { return; } - ListTag positionTag = compound.getListTag("Pos"); - ListTag directionTag = compound.getListTag("Rotation"); EntityType type = EntityTypes.parse(id); if (type != null) { compound.getValue().put("Id", new StringTag(type.getId())); BaseEntity state = new BaseEntity(type, compound); - fc.createEntity(clipboard, positionTag.asDouble(0), positionTag.asDouble(1), positionTag.asDouble(2), (float) directionTag.asDouble(0), (float) directionTag.asDouble(1), state); + + Location loc = compound.getEntityLocation(fc); + fc.createEntity(loc, state); } else { Fawe.debug("Invalid entity: " + id); } @@ -200,81 +202,84 @@ public class SchematicStreamer extends NBTStreamer { } private void fixStates() { - fc.forEach(new LinearClipboard.BlockReader() { - @Override - public > void run(int x, int y, int z, B block) { - BlockType type = block.getBlockType(); - if (BlockCategories.STAIRS.contains(type)) { - Object half = block.getState(PropertyKey.HALF); - Direction facing = block.getState(PropertyKey.FACING); + for (BlockVector3 pos : fc) { + BlockStateHolder block = pos.getBlock(fc); + if (block.getMaterial().isAir()) continue; - BlockVector3 forward = facing.toBlockVector(); - Direction left = facing.getLeft(); - Direction right = facing.getRight(); + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); - BlockStateHolder forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ()); - BlockType forwardType = forwardBlock.getBlockType(); - if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) { - Direction forwardFacing = (Direction) forwardBlock.getState(PropertyKey.FACING); - if (forwardFacing == left) { - BlockStateHolder rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ()); - BlockType rightType = rightBlock.getBlockType(); - if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) { - fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_left")); - } - return; - } else if (forwardFacing == right) { - BlockStateHolder leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ()); - BlockType leftType = leftBlock.getBlockType(); - if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) { - fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_right")); - } - return; + BlockType type = block.getBlockType(); + if (BlockCategories.STAIRS.contains(type)) { + Direction facing = (Direction) block.getState(PropertyKey.FACING); + + BlockVector3 forward = facing.toBlockVector(); + Direction left = facing.getLeft(); + Direction right = facing.getRight(); + + BlockStateHolder forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ()); + BlockType forwardType = forwardBlock.getBlockType(); + if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) { + Direction forwardFacing = (Direction) forwardBlock.getState(PropertyKey.FACING); + if (forwardFacing == left) { + BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ()); + BlockType rightType = rightBlock.getBlockType(); + if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) { + pos.setBlock(fc, block.with(PropertyKey.SHAPE, "inner_left")); } - } - - BlockStateHolder backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ()); - BlockType backwardsType = backwardsBlock.getBlockType(); - if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) { - Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING); - if (backwardsFacing == left) { - BlockStateHolder rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ()); - BlockType rightType = rightBlock.getBlockType(); - if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) { - fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "outer_left")); - } - return; - } else if (backwardsFacing == right) { - BlockStateHolder leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ()); - BlockType leftType = leftBlock.getBlockType(); - if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) { - fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "outer_right")); - } - return; + return; + } else if (forwardFacing == right) { + BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ()); + BlockType leftType = leftBlock.getBlockType(); + if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) { + fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_right")); } + return; } - } else { - int group = group(type); - if (group == -1) return; - BlockStateHolder set = block; - - if (set.getState(PropertyKey.NORTH) == Boolean.FALSE && merge(group, x, y, z - 1)) set = set.with(PropertyKey.NORTH, true); - if (set.getState(PropertyKey.EAST) == Boolean.FALSE && merge(group, x + 1, y, z)) set = set.with(PropertyKey.EAST, true); - if (set.getState(PropertyKey.SOUTH) == Boolean.FALSE && merge(group, x, y, z + 1)) set = set.with(PropertyKey.SOUTH, true); - if (set.getState(PropertyKey.WEST) == Boolean.FALSE && merge(group, x - 1, y, z)) set = set.with(PropertyKey.WEST, true); - - if (group == 2) { - int ns = ((Boolean) set.getState(PropertyKey.NORTH) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.SOUTH) ? 1 : 0); - int ew = ((Boolean) set.getState(PropertyKey.EAST) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.WEST) ? 1 : 0); - if (Math.abs(ns - ew) != 2 || fc.getBlock(x, y + 1, z).getBlockType().getMaterial().isSolid()) { - set = set.with(PropertyKey.UP, true); - } - } - - if (set != block) fc.setBlock(x, y, z, set); } + + BlockState backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ()); + BlockType backwardsType = backwardsBlock.getBlockType(); + if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) { + Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING); + if (backwardsFacing == left) { + BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ()); + BlockType rightType = rightBlock.getBlockType(); + if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) { + pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_left")); + } + return; + } else if (backwardsFacing == right) { + BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ()); + BlockType leftType = leftBlock.getBlockType(); + if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) { + pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_right")); + } + return; + } + } + } else { + int group = group(type); + if (group == -1) return; + BlockStateHolder set = block; + + if (set.getState(PropertyKey.NORTH) == Boolean.FALSE && merge(group, x, y, z - 1)) set = set.with(PropertyKey.NORTH, true); + if (set.getState(PropertyKey.EAST) == Boolean.FALSE && merge(group, x + 1, y, z)) set = set.with(PropertyKey.EAST, true); + if (set.getState(PropertyKey.SOUTH) == Boolean.FALSE && merge(group, x, y, z + 1)) set = set.with(PropertyKey.SOUTH, true); + if (set.getState(PropertyKey.WEST) == Boolean.FALSE && merge(group, x - 1, y, z)) set = set.with(PropertyKey.WEST, true); + + if (group == 2) { + int ns = ((Boolean) set.getState(PropertyKey.NORTH) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.SOUTH) ? 1 : 0); + int ew = ((Boolean) set.getState(PropertyKey.EAST) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.WEST) ? 1 : 0); + if (Math.abs(ns - ew) != 2 || fc.getBlock(x, y + 1, z).getBlockType().getMaterial().isSolid()) { + set = set.with(PropertyKey.UP, true); + } + } + + if (set != block) pos.setBlock(fc, set); } - }, false); + } } private BlockTypeSwitch fullCube = new BlockTypeSwitchBuilder<>(false).add(type -> { @@ -283,7 +288,7 @@ public class SchematicStreamer extends NBTStreamer { }, true).build(); private boolean merge(int group, int x, int y, int z) { - BlockStateHolder block = fc.getBlock(x, y, z); + BlockState block = fc.getBlock(x, y, z); BlockType type = block.getBlockType(); return group(type) == group || fullCube.apply(type); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java index d52a9c674..d7c7ff3f6 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java @@ -2,10 +2,10 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard; import com.boydti.fawe.object.clipboard.LinearClipboard; -import com.boydti.fawe.object.clipboard.OffsetFaweClipboard; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.command.tool.brush.Brush; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Direction; @@ -39,23 +39,23 @@ public class ErodeBrush implements Brush { public void erosion(final EditSession es, int erodeFaces, int erodeRec, int fillFaces, int fillRec, BlockVector3 target, double size) { int brushSize = (int) size + 1; int brushSizeSquared = (int) (size * size); - int dimension = brushSize * 2 + 1; - LinearClipboard buffer1 = new OffsetFaweClipboard(new CPUOptimizedClipboard(dimension, dimension, dimension), brushSize); - LinearClipboard buffer2 = new OffsetFaweClipboard(new CPUOptimizedClipboard(dimension, dimension, dimension), brushSize); + BlockVector3 dimension = BlockVector3.ONE.multiply(brushSize * 2 + 1); + Clipboard buffer1 = new CPUOptimizedClipboard(dimension); + Clipboard buffer2 = new CPUOptimizedClipboard(dimension); final int bx = target.getBlockX(); final int by = target.getBlockY(); final int bz = target.getBlockZ(); - for (int x = -brushSize; x <= brushSize; x++) { + for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { int x0 = x + bx; - for (int y = -brushSize; y <= brushSize; y++) { + for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { int y0 = y + by; - for (int z = -brushSize; z <= brushSize; z++) { + for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { int z0 = z + bz; BlockState state = es.getBlock(x0, y0, z0); - buffer1.setBlock(x, y, z, state); - buffer2.setBlock(x, y, z, state); + buffer1.setBlock(relx, rely, relz, state); + buffer2.setBlock(relx, rely, relz, state); } } } @@ -70,30 +70,28 @@ public class ErodeBrush implements Brush { fillIteration(brushSize, brushSizeSquared, fillFaces, swap % 2 == 0 ? buffer1 : buffer2, swap % 2 == 1 ? buffer1 : buffer2); swap++; } - LinearClipboard finalBuffer = swap % 2 == 0 ? buffer1 : buffer2; + Clipboard finalBuffer = swap % 2 == 0 ? buffer1 : buffer2; - finalBuffer.forEach(new LinearClipboard.BlockReader() { - @Override - public > void run(int x, int y, int z, B block) { - es.setBlock(x + bx, y + by, z + bz, block); - } - }, true); + for (BlockVector3 pos : finalBuffer) { + BlockState block = pos.getBlock(finalBuffer); + es.setBlock(pos.getX() + bx - brushSize, pos.getY() + by - brushSize, pos.getZ() + bz - brushSize, block); + } } private void fillIteration(int brushSize, int brushSizeSquared, int fillFaces, - LinearClipboard current, LinearClipboard target) { + Clipboard current, Clipboard target) { int[] frequency = null; - for (int x = -brushSize; x <= brushSize; x++) { + for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { int x2 = x * x; - for (int z = -brushSize; z <= brushSize; z++) { + for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { int x2y2 = x2 + z * z; - for (int y = -brushSize; y <= brushSize; y++) { + for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { int cube = x2y2 + y * y; - target.setBlock(x, y, z, current.getBlock(x, y, z)); + target.setBlock(x, y, z, current.getBlock(relx, rely, relz)); if (cube >= brushSizeSquared) { continue; } - BaseBlock state = current.getBlock(x, y, z); + BaseBlock state = current.getFullBlock(relx, rely, relz); if (state.getBlockType().getMaterial().isMovementBlocker()) { continue; } @@ -106,7 +104,7 @@ public class ErodeBrush implements Brush { Arrays.fill(frequency, 0); } for (BlockVector3 offs : FACES_TO_CHECK) { - BaseBlock next = current.getBlock(x + offs.getBlockX(), y + offs.getBlockY(), z + offs.getBlockZ()); + BaseBlock next = current.getFullBlock(relx + offs.getBlockX(), rely + offs.getBlockY(), relz + offs.getBlockZ()); if (!next.getBlockType().getMaterial().isMovementBlocker()) { continue; } @@ -118,7 +116,7 @@ public class ErodeBrush implements Brush { } } if (total >= fillFaces) { - target.setBlock(x, y, z, highestState); + target.setBlock(relx, rely, relz, highestState); } } } @@ -126,19 +124,20 @@ public class ErodeBrush implements Brush { } private void erosionIteration(int brushSize, int brushSizeSquared, int erodeFaces, - LinearClipboard current, LinearClipboard target) { + Clipboard current, Clipboard target) { int[] frequency = null; - for (int x = -brushSize; x <= brushSize; x++) { + + for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) { int x2 = x * x; - for (int z = -brushSize; z <= brushSize; z++) { + for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) { int x2y2 = x2 + z * z; - for (int y = -brushSize; y <= brushSize; y++) { + for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) { int cube = x2y2 + y * y; - target.setBlock(x, y, z, current.getBlock(x, y, z)); + target.setBlock(x, y, z, current.getBlock(relx, rely, relz)); if (cube >= brushSizeSquared) { continue; } - BaseBlock state = current.getBlock(x, y, z); + BaseBlock state = current.getFullBlock(relx, rely, relz); if (!state.getBlockType().getMaterial().isMovementBlocker()) { continue; } @@ -151,7 +150,7 @@ public class ErodeBrush implements Brush { Arrays.fill(frequency, 0); } for (BlockVector3 offs : FACES_TO_CHECK) { - BaseBlock next = current.getBlock(x + offs.getBlockX(), y + offs.getBlockY(), z + offs.getBlockZ()); + BaseBlock next = current.getFullBlock(relx + offs.getBlockX(), rely + offs.getBlockY(), relz + offs.getBlockZ()); if (next.getBlockType().getMaterial().isMovementBlocker()) { continue; } @@ -163,7 +162,7 @@ public class ErodeBrush implements Brush { } } if (total >= erodeFaces) { - target.setBlock(x, y, z, highestState); + target.setBlock(relx, rely, relz, highestState); } } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java index 2d19b80fe..8fa1e4b14 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java @@ -21,6 +21,7 @@ import com.sk89q.worldedit.world.block.BlockTypes; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -135,44 +136,7 @@ public class CPUOptimizedClipboard extends LinearClipboard { } @Override - public void forEach(final BlockReader task, boolean air) { - if (air) { - for (int y = 0, index = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - BaseBlock block = getFullBlock(index); - task.run(x, y, z, block); - } - } - } - } else { - for (int y = 0, index = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - BaseBlock block = getFullBlock(index); - if (!block.getMaterial().isAir()) { - task.run(x, y, z, block); - } - } - } - } - } - } - - @Override - public void streamOrdinals(NBTStreamer.ByteReader task) { - int index = 0; - for (int y = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++) { - task.run(index, states[index++]); - } - } - } - } - - @Override - public List getTileEntities() { + public Collection getTileEntities() { convertTilesToIndex(); for (Map.Entry entry : nbtMapIndex.entrySet()) { int index = entry.getKey(); @@ -188,7 +152,7 @@ public class CPUOptimizedClipboard extends LinearClipboard { values.put("z", new IntTag(z)); } } - return new ArrayList<>(nbtMapIndex.values()); + return nbtMapIndex.values(); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java index 6bf6fd00c..ac1c6e8d0 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java @@ -39,11 +39,13 @@ import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; /** @@ -129,7 +131,6 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable if (braf.length() - HEADER_SIZE == (getVolume() << 1) + getArea()) { hasBiomes = true; } - autoCloseTask(); } catch (IOException e) { throw new RuntimeException(e); } @@ -283,105 +284,14 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable } } - private void autoCloseTask() { -// TaskManager.IMP.laterAsync(new Runnable() { -// @Override -// public void run() { -// if (raf != null && System.currentTimeMillis() - lastAccessed > 10000) { -// close(); -// } else if (raf == null) { -// return; -// } else { -// TaskManager.IMP.laterAsync(this, 200); -// } -// } -// }, 200); - } - private int ylast; private int ylasti; private int zlast; private int zlasti; @Override - public void streamOrdinals(NBTStreamer.ByteReader task) { - try { - byteBuffer.force(); - int pos = HEADER_SIZE; - int index = 0; - for (int y = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, pos += 2) { - char ordinal = byteBuffer.getChar(pos); - task.run(index++, ordinal); - } - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - - @Override - public List getTileEntities() { - return new ArrayList<>(nbtMap.values()); - } - - @Override - public void forEach(BlockReader task, boolean air) { - byteBuffer.force(); - int pos = HEADER_SIZE; - IntegerTrio trio = new IntegerTrio(); - final boolean hasTile = !nbtMap.isEmpty(); - if (air) { - if (hasTile) { - for (int y = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, pos += 2) { - int combinedId = byteBuffer.getChar(pos); - BlockState state = BlockState.getFromOrdinal(combinedId); - if (state.getMaterial().hasContainer()) { - trio.set(x, y, z); - CompoundTag nbt = nbtMap.get(trio); - if (nbt != null) { - task.run(x, y, z, state.toBaseBlock(nbt)); - continue; - } - } - task.run(x, y, z, state); - } - } - } - } else { - for (int y = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, pos += 2) { - int combinedId = byteBuffer.getChar(pos); - BlockState state = BlockState.getFromOrdinal(combinedId); - task.run(x, y, z, state); - } - } - } - } - } else { - for (int y = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, pos += 2) { - char combinedId = byteBuffer.getChar(pos); - BlockState state = BlockState.getFromOrdinal(combinedId); - if (state.getMaterial().hasContainer()) { - trio.set(x, y, z); - CompoundTag nbt = nbtMap.get(trio); - if (nbt != null) { - task.run(x, y, z, state.toBaseBlock(nbt)); - continue; - } - task.run(x, y, z, state); - } - } - } - } - } + public Collection getTileEntities() { + return nbtMap.values(); } public int getIndex(int x, int y, int z) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/LinearClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/LinearClipboard.java index f136981da..82ec53fca 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/LinearClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/LinearClipboard.java @@ -1,7 +1,10 @@ package com.boydti.fawe.object.clipboard; +import com.boydti.fawe.beta.AbstractFilterBlock; +import com.boydti.fawe.beta.SingleFilterBlock; import com.boydti.fawe.jnbt.NBTStreamer; import com.boydti.fawe.util.ReflectionUtils; +import com.google.common.collect.ForwardingIterator; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.Tag; @@ -9,34 +12,26 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.collection.DoubleArrayList; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; import java.io.Closeable; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; /** * Best used when clipboard selections are small, or using legacy formats * (Small being < Integer.MAX_VALUE/BLOCK_SIZE_BYTES blocks) */ -public abstract class LinearClipboard implements Clipboard, Closeable { - private final BlockVector3 size; - private final int area; - private final int volume; - private BlockVector3 origin; - +public abstract class LinearClipboard extends SimpleClipboard implements Clipboard, Closeable { public LinearClipboard(BlockVector3 dimensions) { - this.size = dimensions; - long longVolume = (long) getWidth() * (long) getHeight() * (long) getLength(); - if (longVolume >= Integer.MAX_VALUE >> 2) { - throw new IllegalArgumentException("Dimensions are too large for this clipboard format."); - } - this.area = getWidth() * getLength(); - this.volume = (int) longVolume; - this.origin = BlockVector3.ZERO; + super(dimensions); } public abstract > boolean setBlock(int i, B block); @@ -47,99 +42,15 @@ public abstract class LinearClipboard implements Clipboard, Closeable { public abstract BiomeType getBiome(int index); - public void setOrigin(BlockVector3 offset) { - this.origin = offset; - } - - @Override - public BlockVector3 getOrigin() { - return origin; - } - - @Override - public BlockVector3 getMinimumPoint() { - return BlockVector3.ZERO; - } - - @Override - public BlockVector3 getMaximumPoint() { - return size.subtract(BlockVector3.ONE); - } - - @Override - public Region getRegion() { - return new CuboidRegion(BlockVector3.at(0, 0, 0), BlockVector3.at(getWidth() - 1, getHeight() - 1, getLength() - 1)); - } - - public final BlockVector3 getDimensions() { - return size; - } - - public final int getWidth() { - return size.getBlockX(); - } - - public final int getHeight() { - return size.getBlockY(); - } - - public final int getLength() { - return size.getBlockZ(); - } - - public int getArea() { - return area; - } - - public int getVolume() { - return volume; - } - /** * The locations provided are relative to the clipboard min * * @param task * @param air */ - public abstract void forEach(BlockReader task, boolean air); - - public interface BlockReader { - > void run(int x, int y, int z, B block); - } - public abstract void streamBiomes(NBTStreamer.ByteReader task); - public void streamOrdinals(NBTStreamer.ByteReader task) { - forEach(new BlockReader() { - private int index; - - @Override - public > void run(int x, int y, int z, B block) { - task.run(index++, block.getOrdinal()); - } - }, true); - } - - public List getTileEntities() { - final List tiles = new ArrayList<>(); - forEach(new BlockReader() { - - @Override - public > void run(int x, int y, int z, B block) { - if(!(block instanceof BaseBlock)) return; - BaseBlock base = (BaseBlock)block; - CompoundTag tag = base.getNbtData(); - if (tag != null) { - Map values = ReflectionUtils.getMap(tag.getValue()); - values.put("x", new IntTag(x)); - values.put("y", new IntTag(y)); - values.put("z", new IntTag(z)); - tiles.add(tag); - } - } - }, false); - return tiles; - } + public abstract Collection getTileEntities(); public void close() {} @@ -149,4 +60,47 @@ public abstract class LinearClipboard implements Clipboard, Closeable { protected void finalize() { close(); } + + @Override + public Iterator iterator() { + Iterator iter = getRegion().iterator_old(); + LinearFilter filter = new LinearFilter(); + + return new ForwardingIterator() { + @Override + protected Iterator delegate() { + return iter; + } + + @Override + public BlockVector3 next() { + return filter.next(super.next()); + } + }; + } + + private class LinearFilter extends AbstractFilterBlock { + private int index = -1; + private BlockVector3 position; + + private LinearFilter next(BlockVector3 position) { + this.position = position; + index++; + return this; + } + @Override + public BaseBlock getFullBlock() { + return LinearClipboard.this.getFullBlock(index); + } + + @Override + public void setFullBlock(BaseBlock block) { + LinearClipboard.this.setBlock(index, block); + } + + @Override + public BlockVector3 getPosition() { + return position; + } + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java index 9338079e2..6cae8c40d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java @@ -21,6 +21,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -193,20 +194,7 @@ public class MemoryOptimizedClipboard extends LinearClipboard { } @Override - public void streamOrdinals(NBTStreamer.ByteReader task) { - int index = 0; - for (int y = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int id = getOrdinal(index); - task.run(index, id); - } - } - } - } - - @Override - public List getTileEntities() { + public Collection getTileEntities() { convertTilesToIndex(); for (Map.Entry entry : nbtMapIndex.entrySet()) { int index = entry.getKey(); @@ -222,7 +210,7 @@ public class MemoryOptimizedClipboard extends LinearClipboard { values.put("z", new IntTag(z)); } } - return new ArrayList<>(nbtMapIndex.values()); + return nbtMapIndex.values(); } private int ylast; @@ -254,31 +242,6 @@ public class MemoryOptimizedClipboard extends LinearClipboard { return base; } - @Override - public void forEach(final BlockReader task, final boolean air) { - if (air) { - for (int y = 0, index = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - BaseBlock block = getFullBlock(index); - task.run(x, y, z, block); - } - } - } - } else { - for (int y = 0, index = 0; y < getHeight(); y++) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - BaseBlock block = getFullBlock(index); - if (!block.getMaterial().isAir()) { - task.run(x, y, z, block); - } - } - } - } - } - } - public int size() { saveCombinedIds(); int total = 0; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java deleted file mode 100644 index dbc63b777..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.boydti.fawe.object.clipboard; - -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.extent.clipboard.Clipboard; -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.BlockStateHolder; - -public class OffsetClipboard extends DelegateClipboard { - private final int ox, oy, oz; - - public OffsetClipboard(Clipboard parent, int ox, int oy, int oz) { - super(parent); - this.ox = ox; - this.oy = oy; - this.oz = oz; - } - - @Override - public Region getRegion() { - return parent.getRegion(); - } - - @Override - public BaseBlock getBlock(int x, int y, int z) { - return super.getBlock(x + ox, y + oy, z + oz); - } - - @Override - public > boolean setBlock(int x, int y, int z, B block) { - return super.setBlock(ox + x, oy + y, oz + z, block); - } - - @Override - public boolean setBiome(int x, int z, BiomeType biome) { - return super.setBiome(ox + x, oz + z, biome); - } - - @Override - public BiomeType getBiome(int x, int z) { - return super.getBiome(ox + x, oz + z); - } - - @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { - return super.setTile(ox + x, oy + y, oz + z, tag); - } - - @Override - public void forEach(final BlockReader task, boolean air) { - super.forEach(new BlockReader() { - @Override - public > void run(int x, int y, int z, B block) { - task.run(x - ox, y - oy, z - oz, block); - } - }, air); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ReadOnlyClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ReadOnlyClipboard.java index f72afb758..f901efea7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ReadOnlyClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ReadOnlyClipboard.java @@ -5,17 +5,24 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; + +import javax.annotation.Nullable; import java.util.List; -public abstract class ReadOnlyClipboard extends LinearClipboard { +public abstract class ReadOnlyClipboard extends SimpleClipboard { public final Region region; public ReadOnlyClipboard(Region region) { + super(region.getDimensions()); this.region = region; } @@ -32,52 +39,10 @@ public abstract class ReadOnlyClipboard extends LinearClipboard { } @Override - public BlockVector3 getDimensions() { - return region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); - } - - @Override - public void setDimensions(BlockVector3 dimensions) { + public boolean setBiome(int x, int y, int z, BiomeType biome) { throw new UnsupportedOperationException("Clipboard is immutable"); } - @Override - public BaseBlock getBlock(int index) { - throw new UnsupportedOperationException("World based clipboards do not provide index access"); - } - - @Override - public BiomeType getBiome(int index) { - throw new UnsupportedOperationException("World based clipboards do not provide index access"); - } - - @Override - public boolean setBiome(int x, int z, BiomeType biome) { - throw new UnsupportedOperationException("Clipboard is immutable"); - } - - @Override - public void setBiome(int index, BiomeType biome) { - throw new UnsupportedOperationException("Clipboard is immutable"); - } - - @Override - public void streamBiomes(NBTStreamer.ByteReader task) { - BlockVector3 dim = getDimensions(); - int index = 0; - for (int z = 0; z <= dim.getBlockZ(); z++) { - for (int x = 0; x <= dim.getBlockX(); x++, index++) { - task.run(index, getBiome(x, z).getInternalId()); - } - } - } - - @Override - public abstract BaseBlock getBlock(int x, int y, int z); - - @Override - public abstract BiomeType getBiome(int x, int z); - @Override public abstract List getEntities(); @@ -86,23 +51,18 @@ public abstract class ReadOnlyClipboard extends LinearClipboard { throw new UnsupportedOperationException("Clipboard is immutable"); } - @Override - public boolean setBlock(int index, BlockStateHolder block) { - throw new UnsupportedOperationException("Clipboard is immutable"); - } - @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { throw new UnsupportedOperationException("Clipboard is immutable"); } @Override - public Entity createEntity(Extent world, double x, double y, double z, float yaw, float pitch, BaseEntity entity) { + public Entity createEntity(Location location, BaseEntity entity) { throw new UnsupportedOperationException("Clipboard is immutable"); } @Override - public boolean remove(ClipboardEntity clipboardEntity) { + public void removeEntity(Entity entity) { throw new UnsupportedOperationException("Clipboard is immutable"); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/SimpleClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/SimpleClipboard.java new file mode 100644 index 000000000..b614e5bef --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/SimpleClipboard.java @@ -0,0 +1,81 @@ +package com.boydti.fawe.object.clipboard; + +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Region; + +import java.io.Closeable; + +public abstract class SimpleClipboard implements Clipboard, Closeable { + private final BlockVector3 size; + private final int area; + private final int volume; + private BlockVector3 origin; + + public SimpleClipboard(BlockVector3 dimensions) { + this.size = dimensions; + long longVolume = (long) getWidth() * (long) getHeight() * (long) getLength(); + if (longVolume >= Integer.MAX_VALUE >> 2) { + throw new IllegalArgumentException("Dimensions are too large for this clipboard format."); + } + this.area = getWidth() * getLength(); + this.volume = (int) longVolume; + this.origin = BlockVector3.ZERO; + } + + @Override + public void setOrigin(BlockVector3 offset) { + this.origin = offset; + } + + @Override + public BlockVector3 getOrigin() { + return origin; + } + + @Override + public BlockVector3 getMinimumPoint() { + return BlockVector3.ZERO; + } + + @Override + public BlockVector3 getMaximumPoint() { + return size.subtract(BlockVector3.ONE); + } + + @Override + public Region getRegion() { + return new CuboidRegion(BlockVector3.at(0, 0, 0), BlockVector3.at(getWidth() - 1, getHeight() - 1, getLength() - 1)); + } + + @Override + public final BlockVector3 getDimensions() { + return size; + } + + @Override + public final int getWidth() { + return size.getBlockX(); + } + + @Override + public final int getHeight() { + return size.getBlockY(); + } + + @Override + public final int getLength() { + return size.getBlockZ(); + } + + @Override + public int getArea() { + return area; + } + + @Override + public int getVolume() { + return volume; + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java index bdf159e48..ff3d07741 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java @@ -17,6 +17,8 @@ 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.BlockTypes; + +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -45,7 +47,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { } @Override - public BaseBlock getBlock(int x, int y, int z) { + public BaseBlock getFullBlock(int x, int y, int z) { return extent.getFullBlock(BlockVector3.at(mx + x, my + y, mz + z)); } @@ -54,7 +56,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { } @Override - public BiomeType getBiome(int x, int z) { + public BiomeType getBiomeType(int x, int z) { return extent.getBiome(MutableBlockVector2.setComponents(mx + x, mz + z)); } @@ -70,84 +72,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { } @Override - public void forEach(BlockReader task, boolean air) { - BlockVector3 min = region.getMinimumPoint(); - BlockVector3 max = region.getMaximumPoint(); - MutableBlockVector3 pos = new MutableBlockVector3(); - if (region instanceof CuboidRegion) { - if (air) { - ((CuboidRegion) region).setUseOldIterator(true); - RegionVisitor visitor = new RegionVisitor(region, pos1 -> { - BaseBlock block = getBlockAbs(pos1.getBlockX(), pos1.getBlockY(), pos1.getBlockZ()); - int x = pos1.getBlockX() - mx; - int y = pos1.getBlockY() - my; - int z = pos1.getBlockZ() - mz; - if (block.hasNbtData()) { - Map values = ReflectionUtils.getMap(block.getNbtData().getValue()); - values.put("x", new IntTag(x)); - values.put("y", new IntTag(y)); - values.put("z", new IntTag(z)); - } - task.run(x, y, z, block); - return true; - }); - Operations.completeBlindly(visitor); - } else { - CuboidRegion cuboidEquivalent = new CuboidRegion(region.getMinimumPoint(), region.getMaximumPoint()); - cuboidEquivalent.setUseOldIterator(true); - RegionVisitor visitor = new RegionVisitor(cuboidEquivalent, new RegionFunction() { - @Override - public boolean apply(BlockVector3 pos) throws WorldEditException { - int x = pos.getBlockX() - mx; - int y = pos.getBlockY() - my; - int z = pos.getBlockZ() - mz; - if (region.contains(pos)) { - BaseBlock block = extent.getFullBlock(pos); - if (block.hasNbtData()) { - Map values = ReflectionUtils.getMap(block.getNbtData().getValue()); - values.put("x", new IntTag(x)); - values.put("y", new IntTag(y)); - values.put("z", new IntTag(z)); - } - if (!block.getBlockType().getMaterial().isAir()) { - task.run(x, y, z, block); - } - } + public void close() throws IOException { - return true; - } - }); - Operations.completeBlindly(visitor); - } - } else { - for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { - pos.mutY(y); - int yy = pos.getBlockY() - my; - for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { - pos.mutZ(z); - int zz = pos.getBlockZ() - mz; - for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { - pos.mutX(x); - int xx = pos.getBlockX() - mx; - if (region.contains(pos)) { -// BlockState block = getBlockAbs(x, y, z); - BaseBlock block = extent.getFullBlock(pos); - if (!air && block.getBlockType().getMaterial().isAir()) { - continue; - } - if (block.hasNbtData()) { - Map values = ReflectionUtils.getMap(block.getNbtData().getValue()); - values.put("x", new IntTag(xx)); - values.put("y", new IntTag(yy)); - values.put("z", new IntTag(zz)); - } - task.run(xx, yy, zz, block); - } else if (air) { - task.run(xx, yy, zz, BlockTypes.AIR.getDefaultState()); - } - } - } - } - } } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java index 7340f9959..2e8a3e797 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java @@ -6,6 +6,8 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; +import java.io.IOException; + public class WorldCutClipboard extends WorldCopyClipboard { public WorldCutClipboard(EditSession editSession, Region region, boolean copyEntities, boolean copyBiome) { super(editSession, region, copyEntities, copyBiome); @@ -16,7 +18,7 @@ public class WorldCutClipboard extends WorldCopyClipboard { } @Override - public BaseBlock getBlock(int x, int y, int z) { + public BaseBlock getFullBlock(int x, int y, int z) { int xx = mx + x; int yy = my + y; int zz = mz + z; @@ -33,8 +35,7 @@ public class WorldCutClipboard extends WorldCopyClipboard { } @Override - public void forEach(BlockReader task, boolean air) { - super.forEach(task, air); + public void close() throws IOException { if (extent instanceof EditSession) { ((EditSession) extent).flushQueue(); } else { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index 2d9e24f63..417631377 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -21,6 +21,9 @@ package com.sk89q.worldedit.extent; import static com.google.common.base.Preconditions.checkNotNull; +import com.boydti.fawe.beta.AbstractFilterBlock; +import com.boydti.fawe.beta.ExtentFilterBlock; +import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.IBatchProcessor; import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.clipboard.WorldCopyClipboard; @@ -65,6 +68,7 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.UUID; @@ -649,4 +653,16 @@ public interface Extent extends InputExtent, OutputExtent { default Extent disableHistory() { return this; } + + default T apply(Region region, T filter) { + return apply((Iterable) region, filter); + } + + default T apply(Iterable positions, T filter) { + ExtentFilterBlock block = new ExtentFilterBlock(this); + for (BlockVector3 pos : positions) { + filter.applyBlock(block.init(pos)); + } + return filter; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java index 04b3bb590..bf341f006 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java @@ -19,19 +19,12 @@ package com.sk89q.worldedit.extent.clipboard; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.clipboard.DelegateClipboard; -import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard; -import com.boydti.fawe.object.clipboard.LinearClipboard; -import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; @@ -41,15 +34,14 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; -import jdk.vm.ci.meta.Local; +import javax.annotation.Nullable; import java.io.Closeable; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.UUID; -import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; /** * Stores block data as a multi-dimensional array of {@link BlockState}s and @@ -189,46 +181,62 @@ public class BlockArrayClipboard extends DelegateClipboard implements Clipboard, @Override public boolean setBiome(BlockVector2 position, BiomeType biome) { - int x = position.getBlockX()- origin.getX(); - int z = position.getBlockZ()- origin.getZ(); + int x = position.getBlockX() - origin.getX(); + int z = position.getBlockZ() - origin.getZ(); return getParent().setBiome(x, 0, z, biome); } @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { - return parent.setBiome(x, y, z, biome); + x -= origin.getX(); + y -= origin.getY(); + z -= origin.getZ(); + return getParent().setBiome(x, y, z, biome); } @Override public List getEntities(Region region) { - return parent.getEntities(region); + region = region.clone(); + region.shift(origin); + return getParent().getEntities(region); } @Override @Nullable public Entity createEntity(Location location, BaseEntity entity) { - return parent.createEntity(location, entity); + return getParent().createEntity(location, entity); } @Override @Nullable public void removeEntity(int x, int y, int z, UUID uuid) { - parent.removeEntity(x, y, z, uuid); + x -= origin.getX(); + y -= origin.getY(); + z -= origin.getZ(); + getParent().removeEntity(x, y, z, uuid); } @Override public BlockState getBlock(int x, int y, int z) { - return parent.getBlock(x, y, z); + x -= origin.getX(); + y -= origin.getY(); + z -= origin.getZ(); + return getParent().getBlock(x, y, z); } @Override public BaseBlock getFullBlock(int x, int y, int z) { - return parent.getFullBlock(x, y, z); + x -= origin.getX(); + y -= origin.getY(); + z -= origin.getZ(); + return getParent().getFullBlock(x, y, z); } @Override public BiomeType getBiomeType(int x, int z) { - return parent.getBiomeType(x, z); + x -= origin.getX(); + z -= origin.getZ(); + return getParent().getBiomeType(x, z); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java index 610d49791..0e9e2f6d3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.extent.clipboard; +import com.boydti.fawe.beta.Filter; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard; import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard; @@ -27,16 +28,19 @@ import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.util.Location; import javax.annotation.Nullable; +import java.util.Iterator; import java.util.UUID; /** * Specifies an object that implements something suitable as a "clipboard." */ -public interface Clipboard extends Extent { +public interface Clipboard extends Extent, Iterable { static Clipboard create(BlockVector3 size, UUID uuid) { if (Settings.IMP.CLIPBOARD.USE_DISK) { return new DiskOptimizedClipboard(size, uuid); @@ -94,4 +98,41 @@ public interface Clipboard extends Extent { * @param entity */ void removeEntity(Entity entity); + + default int getWidth() { + return getDimensions().getBlockX(); + } + + default int getHeight() { + return getDimensions().getBlockY(); + } + + default int getLength() { + return getDimensions().getBlockZ(); + } + + default int getArea() { + return getWidth() * getLength(); + } + + default int getVolume() { + return getWidth() * getHeight() * getLength(); + } + + default Iterator iterator() { + return getRegion().iterator(); + } + + default Iterator iterator2d() { + return Regions.asFlatRegion(getRegion()).asFlatRegion().iterator(); + } + + @Override + default T apply(Region region, T filter) { + if (region.equals(getRegion())) { + return apply(this, filter); + } else { + return apply((Iterable) region, filter); + } + } } 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..7ff757bf0 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 @@ -19,13 +19,15 @@ package com.sk89q.worldedit.function; +import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.FilterBlock; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; /** * Performs a function on points in a region. */ -public interface RegionFunction { +public interface RegionFunction extends Filter { /** * Apply the function to the given position. @@ -36,4 +38,9 @@ public interface RegionFunction { */ boolean apply(BlockVector3 position) throws WorldEditException; + + @Override + default void applyBlock(FilterBlock block) { + apply(block); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java index db39ad5e7..1f1b64c9c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java @@ -31,6 +31,8 @@ import com.sk89q.worldedit.math.transform.AffineTransform; 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 java.util.Comparator; /** @@ -697,7 +699,8 @@ public abstract class BlockVector3 { return orDefault.setBlock(this, BlockState.getFromOrdinal(ordinal)); } - public boolean setBlock(Extent orDefault, BlockState state) { + + public > boolean setBlock(Extent orDefault, T state) { return orDefault.setBlock(this, state); } diff --git a/worldedit-libs/core/build.gradle.kts b/worldedit-libs/core/build.gradle.kts index 4a115d889..1b4dbc30d 100644 --- a/worldedit-libs/core/build.gradle.kts +++ b/worldedit-libs/core/build.gradle.kts @@ -9,7 +9,6 @@ dependencies { exclude(group = "junit", module = "junit") } "shade"("com.github.luben:zstd-jni:1.4.3-1") - "shade"("com.thoughtworks.paranamer:paranamer:2.6") "shade"("com.sk89q.lib:jlibnoise:1.0.0") "shade"("FAWE-Piston:core/build/libs/core-${Versions.PISTON}:lastSuccessfulBuild@jar") "shade"("FAWE-Piston:core-ap/runtime/build/libs/runtime-${Versions.PISTON}:lastSuccessfulBuild@jar")