Added new Extent-compatible Clipboard and BlockArrayClipboard classes.

The goal is to replace use of CuboidClipboard with these new classes.

Support for entities, //flip, //rotate, and //distr still needs to be
re-implemented.

DataException was also removed from BaseBlock because The Base(...)
classes should be "dumb" blocks without any validation.
This commit is contained in:
sk89q
2014-06-29 17:47:08 -07:00
parent eee2c5d9f4
commit 09eb36dc5e
21 changed files with 571 additions and 365 deletions

View File

@ -22,17 +22,31 @@ package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld.KillFlags;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.command.UtilityCommands.FlagContainer;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.brush.*;
import com.sk89q.worldedit.command.tool.brush.ButcherBrush;
import com.sk89q.worldedit.command.tool.brush.ClipboardBrush;
import com.sk89q.worldedit.command.tool.brush.CylinderBrush;
import com.sk89q.worldedit.command.tool.brush.GravityBrush;
import com.sk89q.worldedit.command.tool.brush.HollowCylinderBrush;
import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush;
import com.sk89q.worldedit.command.tool.brush.SmoothBrush;
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional;
@ -128,14 +142,15 @@ public class BrushCommands {
@CommandPermissions("worldedit.brush.clipboard")
public void clipboardBrush(Player player, LocalSession session, EditSession editSession, @Switch('a') boolean ignoreAir) throws WorldEditException {
CuboidClipboard clipboard = session.getClipboard();
Clipboard clipboard = session.getClipboard();
if (clipboard == null) {
player.printError("Copy something first.");
return;
}
Vector size = clipboard.getSize();
Region region = clipboard.getRegion();
Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
worldEdit.checkMaxBrushRadius(size.getBlockX());
worldEdit.checkMaxBrushRadius(size.getBlockY());

View File

@ -21,18 +21,29 @@ package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.World;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
@ -67,31 +78,16 @@ public class ClipboardCommands {
max = 0
)
@CommandPermissions("worldedit.clipboard.copy")
public void copy(Player player, LocalSession session, EditSession editSession, @Switch('e') boolean copyEntities) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
Vector pos = session.getPlacementPosition(player);
CuboidClipboard clipboard = new CuboidClipboard(
max.subtract(min).add(Vector.ONE),
min, min.subtract(pos));
if (region instanceof CuboidRegion) {
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
}
if (copyEntities) {
for (LocalEntity entity : player.getWorld().getEntities(region)) {
clipboard.storeEntity(entity);
}
}
public void copy(Player player, LocalSession session, EditSession editSession,
@Selection Region region, @Switch('e') boolean copyEntities) throws WorldEditException {
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
clipboard.setOffset(region.getMinimumPoint().subtract(session.getPlacementPosition(player)));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
Operations.completeLegacy(copy);
session.setClipboard(clipboard);
player.print("Block(s) copied.");
player.print(region.getArea() + " block(s) were copied.");
}
@Command(
@ -108,36 +104,17 @@ public class ClipboardCommands {
)
@CommandPermissions("worldedit.clipboard.cut")
@Logging(REGION)
public void cut(Player player, LocalSession session, EditSession editSession, @Optional("air") BaseBlock block, @Switch('e') boolean copyEntities) throws WorldEditException {
World world = player.getWorld();
Region region = session.getSelection(world);
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
Vector pos = session.getPlacementPosition(player);
CuboidClipboard clipboard = new CuboidClipboard(
max.subtract(min).add(Vector.ONE),
min, min.subtract(pos));
if (region instanceof CuboidRegion) {
clipboard.copy(editSession);
} else {
clipboard.copy(editSession, region);
}
if (copyEntities) {
LocalEntity[] entities = world.getEntities(region);
for (LocalEntity entity : entities) {
clipboard.storeEntity(entity);
}
world.killEntities(entities);
}
public void cut(Player player, LocalSession session, EditSession editSession,
@Selection Region region, @Optional("air") Pattern leavePattern, @Switch('e') boolean copyEntities) throws WorldEditException {
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
clipboard.setOffset(region.getMinimumPoint().subtract(session.getPlacementPosition(player)));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
Operations.completeLegacy(copy);
session.setClipboard(clipboard);
editSession.setBlocks(region, block);
player.print("Block(s) cut.");
player.print(region.getArea() + " block(s) were copied.");
}
@Command(
@ -156,38 +133,28 @@ public class ClipboardCommands {
)
@CommandPermissions("worldedit.clipboard.paste")
@Logging(PLACEMENT)
public void paste(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
public void paste(Player player, LocalSession session, EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
boolean atOrigin = args.hasFlag('o');
boolean pasteNoAir = args.hasFlag('a');
Clipboard clipboard = session.getClipboard();
Vector to = atOrigin ? clipboard.getRegion().getMinimumPoint(): session.getPlacementPosition(player).add(clipboard.getOffset());
ForwardExtentCopy copy = new ForwardExtentCopy(clipboard, clipboard.getRegion(), editSession, to);
if (ignoreAirBlocks) {
copy.setSourceMask(new ExistingBlockMask(clipboard));
}
Operations.completeLegacy(copy);
CuboidClipboard clipboard = session.getClipboard();
Vector pos = atOrigin ? session.getClipboard().getOrigin()
: session.getPlacementPosition(player);
if (atOrigin) {
clipboard.place(editSession, pos, pasteNoAir);
clipboard.pasteEntities(pos);
player.findFreePosition();
player.print("Pasted to copy origin. Undo with //undo");
} else {
clipboard.paste(editSession, pos, pasteNoAir, true);
player.findFreePosition();
player.print("Pasted relative to you. Undo with //undo");
if (selectPasted) {
Region region = clipboard.getRegion();
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max);
session.setRegionSelector(player.getWorld(), selector);
selector.learnChanges();
selector.explainRegionAdjust(player, session);
}
if (args.hasFlag('s')) {
World world = player.getWorld();
Vector pos2 = pos.add(clipboard.getSize().subtract(1, 1, 1));
if (!atOrigin) {
pos2 = pos2.add(clipboard.getOffset());
pos = pos.add(clipboard.getOffset());
}
session.setRegionSelector(world, new CuboidRegionSelector(world, pos, pos2));
session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(player, session);
}
player.print("The clipboard has been pasted at " + to.add(clipboard.getRegion().getMinimumPoint()));
}
@Command(
@ -198,17 +165,9 @@ public class ClipboardCommands {
max = 1
)
@CommandPermissions("worldedit.clipboard.rotate")
public void rotate(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int angle = args.getInteger(0);
if (angle % 90 == 0) {
CuboidClipboard clipboard = session.getClipboard();
clipboard.rotate2D(angle);
player.print("Clipboard rotated by " + angle + " degrees.");
} else {
player.printError("Angles must be divisible by 90 degrees.");
}
public void rotate(Player player, LocalSession session, EditSession editSession, CommandContext args) throws CommandException {
// TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again");
}
@Command(
@ -224,11 +183,9 @@ public class ClipboardCommands {
max = 1
)
@CommandPermissions("worldedit.clipboard.flip")
public void flip(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
CuboidClipboard.FlipDirection dir = worldEdit.getFlipDirection(player, args.argsLength() > 0 ? args.getString(0).toLowerCase() : "me");
CuboidClipboard clipboard = session.getClipboard();
clipboard.flip(dir, args.hasFlag('p'));
player.print("Clipboard flipped.");
public void flip(Player player, LocalSession session, EditSession editSession, CommandContext args) throws CommandException {
// TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again");
}
@Command(

View File

@ -19,16 +19,22 @@
package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.*;
import com.sk89q.worldedit.*;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.FilenameResolutionException;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.schematic.SchematicFormat;
import com.sk89q.worldedit.world.DataException;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
@ -64,58 +70,9 @@ public class SchematicCommands {
max = 2
)
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load"}) // TODO: Remove 'clipboard' perm
public void load(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
LocalConfiguration config = worldEdit.getConfiguration();
String fileName;
String formatName;
if (args.argsLength() == 1) {
formatName = null;
fileName = args.getString(0);
} else {
formatName = args.getString(0);
fileName = args.getString(1);
}
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
File f = worldEdit.getSafeOpenFile(player, dir, fileName, "schematic", "schematic");
if (!f.exists()) {
player.printError("Schematic " + fileName + " does not exist!");
return;
}
SchematicFormat format = formatName == null ? null : SchematicFormat.getFormat(formatName);
if (format == null) {
format = SchematicFormat.getFormat(f);
}
if (format == null) {
player.printError("Unknown schematic format: " + formatName);
return;
}
if (!format.isOfFormat(f) && !args.hasFlag('f')) {
player.printError(fileName + " is not of the " + format.getName() + " schematic format!");
return;
}
try {
String filePath = f.getCanonicalPath();
String dirPath = dir.getCanonicalPath();
if (!filePath.substring(0, dirPath.length()).equals(dirPath)) {
player.printError("Schematic could not read or it does not exist.");
} else {
session.setClipboard(format.load(f));
WorldEdit.logger.info(player.getName() + " loaded " + filePath);
player.print(fileName + " loaded. Paste it with //paste");
}
} catch (DataException e) {
player.printError("Load error: " + e.getMessage());
} catch (IOException e) {
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
}
public void load(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
// TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again");
}
@Command(
@ -129,53 +86,8 @@ public class SchematicCommands {
)
@CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"}) // TODO: Remove 'clipboard' perm
public void save(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
LocalConfiguration config = worldEdit.getConfiguration();
SchematicFormat format;
if (args.argsLength() == 1) {
if (SchematicFormat.getFormats().size() == 1) {
format = SchematicFormat.getFormats().iterator().next();
} else {
player.printError("More than one schematic format is available. Please provide the desired format");
return;
}
} else {
format = SchematicFormat.getFormat(args.getString(0));
if (format == null) {
player.printError("Unknown schematic format: " + args.getString(0));
return;
}
}
String filename = args.getString(args.argsLength() - 1);
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
File f = worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
if (!dir.exists()) {
if (!dir.mkdir()) {
player.printError("The storage folder could not be created.");
return;
}
}
try {
// Create parent directories
File parent = f.getParentFile();
if (parent != null && !parent.exists()) {
if (!parent.mkdirs()) {
throw new CommandException("Could not create folder for schematics!");
}
}
format.save(session.getClipboard(), f);
WorldEdit.logger.info(player.getName() + " saved " + f.getCanonicalPath());
player.print(filename + " saved.");
} catch (DataException se) {
player.printError("Save error: " + se.getMessage());
} catch (IOException e) {
player.printError("Schematic could not written: " + e.getMessage());
}
// TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again");
}
@Command(

View File

@ -19,23 +19,13 @@
package com.sk89q.worldedit.command;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandAlias;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
@ -43,18 +33,28 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.CylinderRegionSelector;
import com.sk89q.worldedit.regions.selector.EllipsoidRegionSelector;
import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.SphereRegionSelector;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
/**
* Selection commands.
@ -584,15 +584,15 @@ public class SelectionCommands {
public void size(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
if (args.hasFlag('c')) {
CuboidClipboard clipboard = session.getClipboard();
Vector size = clipboard.getSize();
Clipboard clipboard = session.getClipboard();
Region region = clipboard.getRegion();
Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
Vector offset = clipboard.getOffset();
player.print("Size: " + size);
player.print("Cuboid dimensions (max - min): " + size);
player.print("Offset: " + offset);
player.print("Cuboid distance: " + size.distance(Vector.ONE));
player.print("# of blocks: "
+ (int) (size.getX() * size.getY() * size.getZ()));
player.print("# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
return;
}
@ -610,8 +610,7 @@ public class SelectionCommands {
}
player.print("Size: " + size);
player.print("Cuboid distance: " + region.getMaximumPoint()
.distance(region.getMinimumPoint()));
player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
player.print("# of blocks: " + region.getArea());
}
@ -655,7 +654,7 @@ public class SelectionCommands {
max = 0
)
@CommandPermissions("worldedit.analysis.distr")
public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
int size;
boolean useData = args.hasFlag('d');
@ -663,13 +662,8 @@ public class SelectionCommands {
List<Countable<BaseBlock>> distributionData = null;
if (args.hasFlag('c')) {
CuboidClipboard clip = session.getClipboard();
if (useData) {
distributionData = clip.getBlockDistributionWithData();
} else {
distribution = clip.getBlockDistribution();
}
size = clip.getHeight() * clip.getLength() * clip.getWidth();
// TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again");
} else {
if (useData) {
distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));

View File

@ -19,24 +19,35 @@
package com.sk89q.worldedit.command.tool.brush;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.Region;
public class ClipboardBrush implements Brush {
private CuboidClipboard clipboard;
private Clipboard clipboard;
private boolean noAir;
public ClipboardBrush(CuboidClipboard clipboard, boolean noAir) {
public ClipboardBrush(Clipboard clipboard, boolean noAir) {
this.clipboard = clipboard;
this.noAir = noAir;
}
@Override
public void build(EditSession editSession, Vector pos, Pattern mat, double size) throws MaxChangedBlocksException {
clipboard.place(editSession, pos.subtract(clipboard.getSize().divide(2)), noAir);
Region region = clipboard.getRegion();
Vector centerOffset = region.getCenter().subtract(region.getMinimumPoint());
ForwardExtentCopy copy = new ForwardExtentCopy(clipboard, clipboard.getRegion(), editSession, pos.subtract(centerOffset));
if (noAir) {
copy.setSourceMask(new ExistingBlockMask(clipboard));
}
Operations.completeLegacy(copy);
}
}