Copy/paste/stack/move biomes

This commit is contained in:
Jesse Boyd 2017-07-31 11:56:32 +10:00
parent 36fc147cc2
commit 3726a69f13
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
18 changed files with 256 additions and 48 deletions

View File

@ -33,7 +33,7 @@ public class AbstractDelegateFaweClipboard extends FaweClipboard {
}
@Override
public boolean setBiome(int x, int z, byte biome) {
public boolean setBiome(int x, int z, int biome) {
return parent.setBiome(x, z, biome);
}

View File

@ -7,11 +7,13 @@ import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -24,6 +26,8 @@ public class CPUOptimizedClipboard extends FaweClipboard {
private int width;
private int area;
private int volume;
private byte[] biomes = null;
private byte[] ids;
private byte[] datas;
private byte[] add;
@ -46,6 +50,48 @@ public class CPUOptimizedClipboard extends FaweClipboard {
entities = new HashSet<>();
}
@Override
public boolean hasBiomes() {
return biomes != null;
}
@Override
public boolean setBiome(int x, int z, int biome) {
setBiome(getIndex(x, 0, z), biome);
return true;
}
@Override
public void setBiome(int index, int biome) {
if (biomes == null) {
biomes = new byte[area];
}
biomes[index] = (byte) biome;
}
@Override
public void streamBiomes(NBTStreamer.ByteReader task) {
if (!hasBiomes()) return;
int index = 0;
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, index++) {
task.run(index, biomes[index] & 0xFF);
}
}
}
@Override
public BaseBiome getBiome(int index) {
if (!hasBiomes()) {
return EditSession.nullBiome;
}
return FaweCache.CACHE_BIOME[biomes[index] & 0xFF];
}
@Override
public BaseBiome getBiome(int x, int z) {
return getBiome(getIndex(x, 0, z));
}
public void convertTilesToIndex() {
if (nbtMapLoc.isEmpty()) {

View File

@ -82,8 +82,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
area = width * length;
this.volume = length * width * height;
long size = (braf.length() - HEADER_SIZE) >> 1;
if (size == ((long) width * height * length) + area) {
if ((braf.length() - HEADER_SIZE) == (volume << 1) + area) {
hasBiomes = true;
}
autoCloseTask();
@ -103,16 +102,12 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
if (!hasBiomes) {
try {
hasBiomes = true;
if (mbb != null) {
this.mbb.force();
this.fc.close();
closeDirectBuffer(mbb);
long volume = (long) length * height * width;
this.braf.setLength(HEADER_SIZE + volume + area);
this.fc = braf.getChannel();
this.mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
}
close();
this.braf = new RandomAccessFile(file, "rw");
this.braf.setLength(HEADER_SIZE + (volume << 1) + area);
init();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
@ -125,7 +120,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
}
@Override
public boolean setBiome(int x, int z, byte biome) {
public boolean setBiome(int x, int z, int biome) {
setBiome(getIndex(x, 0, z), biome);
return true;
}
@ -133,7 +128,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override
public void setBiome(int index, int biome) {
if (initBiome()) {
mbb.put(HEADER_SIZE + volume + index, (byte) biome);
mbb.put(HEADER_SIZE + (volume << 1) + index, (byte) biome);
}
}
@ -142,7 +137,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
if (!hasBiomes()) {
return EditSession.nullBiome;
}
int biomeId = mbb.get(HEADER_SIZE + volume + index) & 0xFF;
int biomeId = mbb.get(HEADER_SIZE + (volume << 1) + index) & 0xFF;
return FaweCache.CACHE_BIOME[biomeId];
}
@ -150,9 +145,11 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
public void streamBiomes(NBTStreamer.ByteReader task) {
if (!hasBiomes()) return;
int index = 0;
int offset = HEADER_SIZE + (volume << 1);
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, index++) {
task.run(index, getBiome(index).getId());
int biome = mbb.get(offset + index) & 0xFF;
task.run(index, biome);
}
}
}
@ -268,7 +265,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
}
public DiskOptimizedClipboard(int width, int height, int length) {
this(width, height, length, MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.CLIPBOARD + File.separator + UUID.randomUUID() + ".bd"));
this(width, height, length, MainUtil.getFile(Fawe.imp() != null ? Fawe.imp().getDirectory() : new File("."), Settings.IMP.PATHS.CLIPBOARD + File.separator + UUID.randomUUID() + ".bd"));
}
private void closeDirectBuffer(ByteBuffer cb) {

View File

@ -27,7 +27,7 @@ public abstract class FaweClipboard {
public abstract boolean hasBiomes();
public abstract boolean setBiome(int x, int z, byte biome);
public abstract boolean setBiome(int x, int z, int biome);
public abstract BaseBiome getBiome(int x, int z);

View File

@ -95,7 +95,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
}
@Override
public boolean setBiome(int x, int z, byte biome) {
public boolean setBiome(int x, int z, int biome) {
setBiome(getIndex(x, 0, z), biome);
return true;
}

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.object.clipboard;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.world.biome.BaseBiome;
public class OffsetFaweClipboard extends AbstractDelegateFaweClipboard {
private final int ox, oy, oz;
@ -27,6 +28,16 @@ public class OffsetFaweClipboard extends AbstractDelegateFaweClipboard {
return super.setBlock(ox + x, oy + y, oz + z, block);
}
@Override
public boolean setBiome(int x, int z, int biome) {
return super.setBiome(ox + x, oz + z, biome);
}
@Override
public BaseBiome 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);

View File

@ -20,7 +20,11 @@ public abstract class ReadOnlyClipboard extends FaweClipboard {
}
public static ReadOnlyClipboard of(final EditSession editSession, final Region region) {
return new WorldCopyClipboard(editSession, region);
return of(editSession, region, true, false);
}
public static ReadOnlyClipboard of(final EditSession editSession, final Region region, boolean copyEntities, boolean copyBiomes) {
return new WorldCopyClipboard(editSession, region, copyEntities, copyBiomes);
}
public Region getRegion() {
@ -48,7 +52,7 @@ public abstract class ReadOnlyClipboard extends FaweClipboard {
}
@Override
public boolean setBiome(int x, int z, byte biome) {
public boolean setBiome(int x, int z, int biome) {
throw new UnsupportedOperationException("Clipboard is immutable");
}

View File

@ -16,17 +16,26 @@ import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class WorldCopyClipboard extends ReadOnlyClipboard {
public final int mx, my, mz;
private final boolean hasBiomes;
private final boolean hasEntities;
private MutableBlockVector2D mutableBlockVector2D = new MutableBlockVector2D();
public final EditSession editSession;
public WorldCopyClipboard(EditSession editSession, Region region) {
this(editSession, region, true, false);
}
public WorldCopyClipboard(EditSession editSession, Region region, boolean hasEntities, boolean hasBiomes) {
super(region);
this.hasBiomes = hasBiomes;
this.hasEntities = hasEntities;
final Vector origin = region.getMinimumPoint();
this.mx = origin.getBlockX();
this.my = origin.getBlockY();
@ -50,12 +59,13 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
@Override
public List<? extends Entity> getEntities() {
if (!hasEntities) return new ArrayList<>();
return editSession.getEntities(getRegion());
}
@Override
public boolean hasBiomes() {
return true;
return hasBiomes;
}
@Override

View File

@ -5,6 +5,10 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.regions.Region;
public class WorldCutClipboard extends WorldCopyClipboard {
public WorldCutClipboard(EditSession editSession, Region region, boolean copyEntities, boolean copyBiome) {
super(editSession, region, copyEntities, copyBiome);
}
public WorldCutClipboard(EditSession editSession, Region region) {
super(editSession, region);
}

View File

@ -0,0 +1,31 @@
package com.boydti.fawe.object.function.block;
import com.sk89q.worldedit.MutableBlockVector2D;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.RegionFunction;
public class BiomeCopy implements RegionFunction {
protected final Extent source;
protected final Extent destination;
private final MutableBlockVector2D mPos2d;
public BiomeCopy(Extent source, Extent destination) {
this.source = source;
this.destination = destination;
this.mPos2d = new MutableBlockVector2D();
this.mPos2d.setComponents(Integer.MIN_VALUE, Integer.MIN_VALUE);
}
@Override
public boolean apply(Vector position) throws WorldEditException {
int x = position.getBlockX();
int z = position.getBlockZ();
if (x != mPos2d.getBlockX() || z != mPos2d.getBlockZ()) {
mPos2d.setComponents(x, z);
return destination.setBiome(mPos2d, source.getBiome(mPos2d));
}
return false;
}
}

View File

@ -7,8 +7,8 @@ import com.sk89q.worldedit.function.RegionFunction;
public class SimpleBlockCopy implements RegionFunction {
private final Extent source;
private final Extent destination;
protected final Extent source;
protected final Extent destination;
public SimpleBlockCopy(Extent source, Extent destination) {
this.source = source;

View File

@ -7,6 +7,7 @@ import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MaskTraverser;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.MutableBlockVector2D;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
@ -157,9 +158,15 @@ public class Schematic {
public void paste(Extent extent, WorldData worldData, Vector to, boolean pasteAir, Transform transform) {
checkNotNull(transform);
Region region = clipboard.getRegion();
BlockTransformExtent source = new BlockTransformExtent(clipboard, transform, worldData.getBlockRegistry());
Extent source = clipboard;
if (worldData != null && transform != null) {
source = new BlockTransformExtent(clipboard, transform, worldData.getBlockRegistry());
}
ForwardExtentCopy copy = new ForwardExtentCopy(source, clipboard.getRegion(), clipboard.getOrigin(), extent, to);
copy.setTransform(transform);
if (transform != null) {
copy.setTransform(transform);
}
copy.setCopyBiomes(!(clipboard instanceof BlockArrayClipboard) || ((BlockArrayClipboard) clipboard).IMP.hasBiomes());
if (extent instanceof EditSession) {
EditSession editSession = (EditSession) extent;
Mask sourceMask = editSession.getSourceMask();
@ -175,11 +182,14 @@ public class Schematic {
Operations.completeBlindly(copy);
}
public void paste(Extent extent, Vector to, boolean pasteAir) {
public void paste(Extent extent, Vector to, final boolean pasteAir) {
Region region = clipboard.getRegion().clone();
final int maxY = extent.getMaximumPoint().getBlockY();
final Vector bot = clipboard.getMinimumPoint();
final Vector origin = clipboard.getOrigin();
final boolean copyBiomes = !(clipboard instanceof BlockArrayClipboard) || ((BlockArrayClipboard) clipboard).IMP.hasBiomes();
// Optimize for BlockArrayClipboard
if (clipboard instanceof BlockArrayClipboard && region instanceof CuboidRegion) {
// To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min)
@ -187,29 +197,62 @@ public class Schematic {
final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY();
final int relz = to.getBlockZ() + bot.getBlockZ() - origin.getBlockZ();
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
bac.IMP.forEach(new FaweClipboard.BlockReader() {
@Override
public void run(int x, int y, int z, BaseBlock block) {
try {
extent.setBlock(x + relx, y + rely, z + relz, block);
} catch (WorldEditException e) {
throw new RuntimeException(e);
if (copyBiomes) {
bac.IMP.forEach(new FaweClipboard.BlockReader() {
MutableBlockVector2D mpos2d = new MutableBlockVector2D();
{
mpos2d.setComponents(Integer.MIN_VALUE, Integer.MIN_VALUE);
}
}
}, pasteAir);
@Override
public void run(int x, int y, int z, BaseBlock block) {
try {
int xx = x + relx;
int zz = z + relz;
if (xx != mpos2d.getBlockX() || zz != mpos2d.getBlockZ()) {
mpos2d.setComponents(xx, zz);
extent.setBiome(mpos2d, bac.IMP.getBiome(x, z));
}
if (!pasteAir && block.getId() == 0) {
return;
}
extent.setBlock(xx, y + rely, zz, block);
} catch (WorldEditException e) { throw new RuntimeException(e);}
}
}, true);
} else {
bac.IMP.forEach(new FaweClipboard.BlockReader() {
@Override
public void run(int x, int y, int z, BaseBlock block) {
try {
extent.setBlock(x + relx, y + rely, z + relz, block);
} catch (WorldEditException e) { throw new RuntimeException(e);}
}
}, pasteAir);
}
} else {
// To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin)
final int relx = to.getBlockX() - origin.getBlockX();
final int rely = to.getBlockY() - origin.getBlockY();
final int relz = to.getBlockZ() - origin.getBlockZ();
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
MutableBlockVector2D mpos2d_2 = new MutableBlockVector2D();
MutableBlockVector2D mpos2d = new MutableBlockVector2D();
{
mpos2d.setComponents(Integer.MIN_VALUE, Integer.MIN_VALUE);
}
@Override
public boolean apply(Vector mutable) throws WorldEditException {
BaseBlock block = clipboard.getBlock(mutable);
if (block.getId() == 0 && !pasteAir) {
int xx = mutable.getBlockX() + relx;
int zz = mutable.getBlockZ() + relz;
if (copyBiomes && xx != mpos2d.getBlockX() && zz != mpos2d.getBlockZ()) {
mpos2d.setComponents(xx, zz);
extent.setBiome(mpos2d, clipboard.getBiome(mpos2d_2.setComponents(mutable.getBlockX(), mutable.getBlockZ())));
}
if (!pasteAir && block.getId() == 0) {
return false;
}
extent.setBlock(mutable.getBlockX() + relx, mutable.getBlockY() + rely, mutable.getBlockZ() + relz, block);
extent.setBlock(xx, mutable.getBlockY() + rely, zz, block);
return false;
}
}, (HasFaweQueue) (null));

View File

@ -1968,6 +1968,10 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return this.changes = naturalizer.getAffected();
}
public int stackCuboidRegion(final Region region, final Vector dir, final int count, final boolean copyAir) {
return stackCuboidRegion(region, dir, count, copyAir, true, false);
}
/**
* Stack a cuboid region.
*
@ -1978,13 +1982,15 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int stackCuboidRegion(final Region region, final Vector dir, final int count, final boolean copyAir) {
public int stackCuboidRegion(final Region region, final Vector dir, final int count, final boolean copyAir, boolean copyEntities, boolean copyBiomes) {
checkNotNull(region);
checkNotNull(dir);
checkArgument(count >= 1, "count >= 1 required");
final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
final Vector to = region.getMinimumPoint();
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to);
copy.setCopyEntities(copyEntities);
copy.setCopyBiomes(copyBiomes);
copy.setRepetitions(count);
copy.setTransform(new AffineTransform().translate(dir.multiply(size)));
Mask sourceMask = getSourceMask();
@ -2012,6 +2018,10 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int moveRegion(final Region region, final Vector dir, final int distance, final boolean copyAir, final BaseBlock replacement) {
return moveRegion(region, dir, distance, copyAir, true, false, replacement);
}
public int moveRegion(final Region region, final Vector dir, final int distance, final boolean copyAir, final boolean copyEntities, final boolean copyBiomes, final BaseBlock replacement) {
checkNotNull(region);
checkNotNull(dir);
checkArgument(distance >= 1, "distance >= 1 required");
@ -2038,6 +2048,8 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
};
copy.setCopyBiomes(copyBiomes);
copy.setCopyEntities(copyEntities);
copy.setSourceFunction(remove);
copy.setRepetitions(1);
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));

View File

@ -157,6 +157,7 @@ public class ClipboardCommands extends MethodCommands {
clipboard.setOrigin(session.getPlacementPosition(player));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
copy.setCopyEntities(!skipEntities);
copy.setCopyBiomes(copyBiomes);
Mask sourceMask = editSession.getSourceMask();
if (sourceMask != null) {
new MaskTraverser(sourceMask).reset(editSession);
@ -180,13 +181,14 @@ public class ClipboardCommands extends MethodCommands {
"Flags:\n" +
" -e skips entity copy\n" +
" -m sets a source mask so that excluded blocks become air\n" +
" -b copies biomes\n" +
"WARNING: Pasting entities cannot yet be undone!",
max = 0
)
@CommandPermissions("worldedit.clipboard.lazycut")
public void lazyCut(Player player, LocalSession session, EditSession editSession,
@Selection final Region region, @Switch('e') boolean skipEntities,
@Switch('m') Mask mask) throws WorldEditException {
@Switch('m') Mask mask, @Switch('b') boolean copyBiomes) throws WorldEditException {
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min.getZ() + 1));
@ -202,7 +204,7 @@ public class ClipboardCommands extends MethodCommands {
final int mx = origin.getBlockX();
final int my = origin.getBlockY();
final int mz = origin.getBlockZ();
ReadOnlyClipboard lazyClipboard = new WorldCutClipboard(editSession, region, skipEntities);
ReadOnlyClipboard lazyClipboard = new WorldCutClipboard(editSession, region, !skipEntities, copyBiomes);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, lazyClipboard);
clipboard.setOrigin(session.getPlacementPosition(player));
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorldData()));
@ -218,6 +220,7 @@ public class ClipboardCommands extends MethodCommands {
"Flags:\n" +
" -e skips entity copy\n" +
" -m sets a source mask so that excluded blocks become air\n" +
" -b copies biomes\n" +
"WARNING: Cutting and pasting entities cannot yet be undone!",
min = 0,
max = 1
@ -226,7 +229,7 @@ public class ClipboardCommands extends MethodCommands {
@Logging(REGION)
public void cut(FawePlayer fp, Player player, LocalSession session, EditSession editSession,
@Selection Region region, @Optional("air") Pattern leavePattern, @Switch('e') boolean skipEntities,
@Switch('m') Mask mask, CommandContext context) throws WorldEditException {
@Switch('m') Mask mask, @Switch('b') boolean copyBiomes, CommandContext context) throws WorldEditException {
fp.checkConfirmationRegion(getArguments(context), region);
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
@ -244,6 +247,7 @@ public class ClipboardCommands extends MethodCommands {
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
copy.setCopyEntities(!skipEntities);
copy.setCopyBiomes(copyBiomes);
Mask sourceMask = editSession.getSourceMask();
if (sourceMask != null) {
new MaskTraverser(sourceMask).reset(editSession);
@ -361,6 +365,8 @@ public class ClipboardCommands extends MethodCommands {
"Pastes the clipboard's contents.\n" +
"Flags:\n" +
" -a skips air blocks\n" +
" -b skips pasting biomes\n" +
" -e skips pasting entities\n" +
" -o pastes at the original position\n" +
" -s selects the region after pasting",
min = 0,
@ -369,7 +375,7 @@ public class ClipboardCommands extends MethodCommands {
@CommandPermissions("worldedit.clipboard.paste")
@Logging(PLACEMENT)
public void paste(Player player, LocalSession session, EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('a') boolean ignoreAirBlocks, @Switch('b') boolean ignoreBiomes, @Switch('e') boolean ignoreEntities, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
if (holder.getTransform().isIdentity() && editSession.getSourceMask() == null) {
@ -383,6 +389,8 @@ public class ClipboardCommands extends MethodCommands {
.createPaste(editSession, editSession.getWorldData())
.to(to)
.ignoreAirBlocks(ignoreAirBlocks)
.ignoreBiomes(ignoreBiomes)
.ignoreEntities(ignoreEntities)
.build();
Operations.completeLegacy(operation);

View File

@ -523,7 +523,10 @@ public class RegionCommands extends MethodCommands {
desc = "Move the contents of the selection",
help =
"Moves the contents of the selection.\n" +
"The -s flag shifts the selection to the target location.\n" +
" -s flag shifts the selection to the target location.\n" +
" -b also copies biomes\n" +
" -e ignores entities\n" +
" -a ignores air\n" +
"Optionally fills the old location with <leave-id>.",
min = 0,
max = 3
@ -535,11 +538,14 @@ public class RegionCommands extends MethodCommands {
@Optional("1") @Range(min = 1) int count,
@Optional(Direction.AIM) @Direction Vector direction,
@Optional("air") BaseBlock replace,
@Switch('b') boolean copyBiomes,
@Switch('e') boolean skipEntities,
@Switch('a') boolean skipAir,
@Switch('s') boolean moveSelection,
CommandContext context) throws WorldEditException {
player.checkConfirmationRegion(getArguments(context), region);
int affected = editSession.moveRegion(region, direction, count, true, replace);
int affected = editSession.moveRegion(region, direction, count, !skipAir, !skipEntities, copyBiomes, replace);
if (moveSelection) {
try {
@ -598,12 +604,14 @@ public class RegionCommands extends MethodCommands {
@Optional("1") @Range(min = 1) int count,
@Optional(Direction.AIM) @Direction Vector direction,
@Switch('s') boolean moveSelection,
@Switch('b') boolean copyBiomes,
@Switch('e') boolean skipEntities,
@Switch('a') boolean ignoreAirBlocks, @Switch('m') Mask sourceMask, CommandContext context) throws WorldEditException {
player.checkConfirmationStack(getArguments(context), region, count);
if (sourceMask != null) {
editSession.addSourceMask(sourceMask);
}
int affected = editSession.stackCuboidRegion(region, direction, count, !ignoreAirBlocks);
int affected = editSession.stackCuboidRegion(region, direction, count, !ignoreAirBlocks, !skipEntities, copyBiomes);
if (moveSelection) {
try {

View File

@ -219,12 +219,17 @@ public class BlockArrayClipboard implements Clipboard, LightingExtent {
@Override
public BaseBiome getBiome(Vector2D position) {
return new BaseBiome(0);
int x = position.getBlockX() - mx;
int z = position.getBlockZ() - mz;
return IMP.getBiome(x, z);
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
return false;
int x = position.getBlockX() - mx;
int z = position.getBlockZ() - mz;
IMP.setBiome(x, z, biome.getId());
return true;
}
@Nullable

View File

@ -23,12 +23,14 @@ import com.boydti.fawe.example.MappedFaweQueue;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.extent.BlockTranslateExtent;
import com.boydti.fawe.object.extent.PositionTransformExtent;
import com.boydti.fawe.object.function.block.BiomeCopy;
import com.boydti.fawe.object.function.block.SimpleBlockCopy;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.function.CombinedRegionFunction;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.RegionMaskingFilter;
@ -69,6 +71,7 @@ public class ForwardExtentCopy implements Operation {
private Transform currentTransform = null;
private int affected;
private boolean copyEntities = true;
private boolean copyBiomes = false;
/**
* Create a new copy using the region's lowest minimum point as the
@ -147,6 +150,14 @@ public class ForwardExtentCopy implements Operation {
return copyEntities;
}
public void setCopyBiomes(boolean copyBiomes) {
this.copyBiomes = copyBiomes;
}
public boolean isCopyBiomes() {
return copyBiomes;
}
/**
* Set a mask that gets applied to the source extent.
*
@ -257,6 +268,9 @@ public class ForwardExtentCopy implements Operation {
if (sourceFunction != null) {
copy = new CombinedRegionFunction(copy, sourceFunction);
}
if (copyBiomes && (!(source instanceof BlockArrayClipboard) || ((BlockArrayClipboard) source).IMP.hasBiomes())) {
copy = new CombinedRegionFunction(copy, new BiomeCopy(source, finalDest));
}
RegionVisitor blockVisitor = new RegionVisitor(region, copy, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null);
List<? extends Entity> entities = isCopyEntities() ? source.getEntities(region) : new ArrayList<>();

View File

@ -23,6 +23,7 @@ import com.boydti.fawe.util.MaskTraverser;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
@ -48,6 +49,8 @@ public class PasteBuilder {
private Vector to = new Vector();
private boolean ignoreAirBlocks;
private boolean ignoreBiomes;
private boolean ignoreEntities;
/**
* Create a new instance.
@ -88,6 +91,16 @@ public class PasteBuilder {
return this;
}
public PasteBuilder ignoreBiomes(boolean ignoreBiomes) {
this.ignoreBiomes = ignoreBiomes;
return this;
}
public PasteBuilder ignoreEntities(boolean ignoreEntities) {
this.ignoreEntities = ignoreEntities;
return this;
}
/**
* Build the operation.
*
@ -100,6 +113,8 @@ public class PasteBuilder {
}
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), targetExtent, to);
copy.setTransform(transform);
copy.setCopyEntities(!ignoreEntities);
copy.setCopyBiomes((!ignoreBiomes) && (!(clipboard instanceof BlockArrayClipboard) || ((BlockArrayClipboard) clipboard).IMP.hasBiomes()));
if (targetExtent instanceof EditSession) {
Mask sourceMask = ((EditSession) targetExtent).getSourceMask();
if (sourceMask != null) {