wip clipboard migration

This commit is contained in:
Jesse Boyd 2019-10-31 14:12:23 +01:00
parent 0296d566ed
commit b533408022
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
24 changed files with 663 additions and 697 deletions

View File

@ -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 <T extends BlockStateHolder<T>> 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);
}
}

View File

@ -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 <T extends BlockStateHolder<T>> 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);
}
}

View File

@ -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;
}
}

View File

@ -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 <tt>true</tt> 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 extends Filter> T apply(Region region, T filter) {
final Set<BlockVector2> chunks = region.getChunks();
ChunkFilterBlock block = null;
for (BlockVector2 chunk : chunks) {
block = apply(block, filter, region, chunk.getX(), chunk.getZ());
}
flush();
return filter;
}
}

View File

@ -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 <T extends BlockStateHolder<T>> 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);
}
}

View File

@ -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();
}
}

View File

@ -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 extends Filter> T apply(Region region, T filter) {
// The chunks positions to iterate over
final Set<BlockVector2> 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();
}

View File

@ -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 <B extends BlockStateHolder<B>> 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<com.sk89q.worldedit.world.block.BaseBlock> 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<com.sk89q.worldedit.world.block.BaseBlock> 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<com.sk89q.worldedit.world.block.BaseBlock> 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<com.sk89q.worldedit.world.block.BaseBlock> 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<com.sk89q.worldedit.world.block.BaseBlock> 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<com.sk89q.worldedit.world.block.BaseBlock> 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<Boolean> 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<com.sk89q.worldedit.world.block.BaseBlock> block = fc.getBlock(x, y, z);
BlockState block = fc.getBlock(x, y, z);
BlockType type = block.getBlockType();
return group(type) == group || fullCube.apply(type);
}

View File

@ -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 <B extends BlockStateHolder<B>> 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);
}
}
}

View File

@ -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<CompoundTag> getTileEntities() {
public Collection<CompoundTag> getTileEntities() {
convertTilesToIndex();
for (Map.Entry<Integer, CompoundTag> 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

View File

@ -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<CompoundTag> 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<CompoundTag> getTileEntities() {
return nbtMap.values();
}
public int getIndex(int x, int y, int z) {

View File

@ -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 <B extends BlockStateHolder<B>> 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 {
<B extends BlockStateHolder<B>> 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 <B extends BlockStateHolder<B>> void run(int x, int y, int z, B block) {
task.run(index++, block.getOrdinal());
}
}, true);
}
public List<CompoundTag> getTileEntities() {
final List<CompoundTag> tiles = new ArrayList<>();
forEach(new BlockReader() {
@Override
public <B extends BlockStateHolder<B>> 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<String, Tag> 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<CompoundTag> getTileEntities();
public void close() {}
@ -149,4 +60,47 @@ public abstract class LinearClipboard implements Clipboard, Closeable {
protected void finalize() {
close();
}
@Override
public Iterator<BlockVector3> iterator() {
Iterator<BlockVector3> iter = getRegion().iterator_old();
LinearFilter filter = new LinearFilter();
return new ForwardingIterator<BlockVector3>() {
@Override
protected Iterator<BlockVector3> 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;
}
}
}

View File

@ -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<CompoundTag> getTileEntities() {
public Collection<CompoundTag> getTileEntities() {
convertTilesToIndex();
for (Map.Entry<Integer, CompoundTag> 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;

View File

@ -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 <B extends BlockStateHolder<B>> 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 <B extends BlockStateHolder<B>> void run(int x, int y, int z, B block) {
task.run(x - ox, y - oy, z - oz, block);
}
}, air);
}
}

View File

@ -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<? extends Entity> 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");
}
}

View File

@ -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;
}
}

View File

@ -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<String, Tag> 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<String, Tag> 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<String, Tag> 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());
}
}
}
}
}
}
}

View File

@ -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 {

View File

@ -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 extends Filter> T apply(Region region, T filter) {
return apply((Iterable<BlockVector3>) region, filter);
}
default <T extends Filter> T apply(Iterable<BlockVector3> positions, T filter) {
ExtentFilterBlock block = new ExtentFilterBlock(this);
for (BlockVector3 pos : positions) {
filter.applyBlock(block.init(pos));
}
return filter;
}
}

View File

@ -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<? extends Entity> 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);
}
/**

View File

@ -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<BlockVector3> {
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<BlockVector3> iterator() {
return getRegion().iterator();
}
default Iterator<BlockVector2> iterator2d() {
return Regions.asFlatRegion(getRegion()).asFlatRegion().iterator();
}
@Override
default <T extends Filter> T apply(Region region, T filter) {
if (region.equals(getRegion())) {
return apply(this, filter);
} else {
return apply((Iterable<BlockVector3>) region, filter);
}
}
}

View File

@ -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);
}
}

View File

@ -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 <T extends BlockStateHolder<T>> boolean setBlock(Extent orDefault, T state) {
return orDefault.setBlock(this, state);
}

View File

@ -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")