From 09eb36dc5ea316bc8a06c0a24282020e10f770f0 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 29 Jun 2014 17:47:08 -0700 Subject: [PATCH] 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. --- .../worldedit/bukkit/DefaultNmsBlock.java | 2 +- .../worldedit/forge/TileEntityBaseBlock.java | 6 +- .../com/sk89q/worldedit/LocalSession.java | 7 +- .../com/sk89q/worldedit/blocks/BaseBlock.java | 19 ++- .../sk89q/worldedit/blocks/ChestBlock.java | 35 ++-- .../worldedit/blocks/DispenserBlock.java | 52 +++--- .../sk89q/worldedit/blocks/FurnaceBlock.java | 65 +++---- .../com/sk89q/worldedit/blocks/LazyBlock.java | 9 +- .../worldedit/blocks/MobSpawnerBlock.java | 23 ++- .../com/sk89q/worldedit/blocks/NoteBlock.java | 14 +- .../com/sk89q/worldedit/blocks/SignBlock.java | 14 +- .../sk89q/worldedit/blocks/SkullBlock.java | 14 +- .../worldedit/command/BrushCommands.java | 23 ++- .../worldedit/command/ClipboardCommands.java | 151 ++++++----------- .../worldedit/command/SchematicCommands.java | 118 ++----------- .../worldedit/command/SelectionCommands.java | 56 +++--- .../command/tool/brush/ClipboardBrush.java | 19 ++- .../extent/clipboard/BlockArrayClipboard.java | 160 ++++++++++++++++++ .../worldedit/extent/clipboard/Clipboard.java | 58 +++++++ .../extent/clipboard/StoredEntity.java | 76 +++++++++ .../function/pattern/ClipboardPattern.java | 15 +- 21 files changed, 571 insertions(+), 365 deletions(-) create mode 100644 src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java create mode 100644 src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java create mode 100644 src/main/java/com/sk89q/worldedit/extent/clipboard/StoredEntity.java diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java index 23d5e64e8..8b738923b 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java @@ -134,7 +134,7 @@ public class DefaultNmsBlock extends NmsBlock { } @Override - public void setNbtData(CompoundTag tag) throws DataException { + public void setNbtData(CompoundTag tag) { if (tag == null) { this.nbtData = null; } diff --git a/src/forge/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java b/src/forge/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java index 1a46607a8..a17ac5d43 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java +++ b/src/forge/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.forge; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.TileEntityBlock; -import com.sk89q.worldedit.world.DataException; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; @@ -29,10 +28,7 @@ public class TileEntityBaseBlock extends BaseBlock implements TileEntityBlock { public TileEntityBaseBlock(int type, int data, TileEntity tile) { super(type, data); - try { - setNbtData(NBTConverter.fromNative(copyNbtData(tile))); - } catch (DataException ignored) { - } + setNbtData(NBTConverter.fromNative(copyNbtData(tile))); } private static NBTTagCompound copyNbtData(TileEntity tile) { diff --git a/src/main/java/com/sk89q/worldedit/LocalSession.java b/src/main/java/com/sk89q/worldedit/LocalSession.java index df38b58a5..17b86f3b4 100644 --- a/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -29,6 +29,7 @@ import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; @@ -62,7 +63,7 @@ public class LocalSession { private boolean placeAtPos1 = false; private LinkedList history = new LinkedList(); private int historyPointer = 0; - private CuboidClipboard clipboard; + private Clipboard clipboard; private boolean toolControl = true; private boolean superPickaxe = false; private BlockTool pickaxeMode = new SinglePickaxe(); @@ -326,7 +327,7 @@ public class LocalSession { * @return clipboard, may be null * @throws EmptyClipboardException */ - public CuboidClipboard getClipboard() throws EmptyClipboardException { + public Clipboard getClipboard() throws EmptyClipboardException { if (clipboard == null) { throw new EmptyClipboardException(); } @@ -338,7 +339,7 @@ public class LocalSession { * * @param clipboard */ - public void setClipboard(CuboidClipboard clipboard) { + public void setClipboard(Clipboard clipboard) { this.clipboard = clipboard; } diff --git a/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java b/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java index 497839125..d89ff8e03 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java @@ -100,17 +100,27 @@ public class BaseBlock extends Block implements TileEntityBlock { * @see #setData(int) * @see #setNbtData(CompoundTag) */ - public BaseBlock(int id, int data, CompoundTag nbtData) throws DataException { + public BaseBlock(int id, int data, CompoundTag nbtData) { setId(id); setData(data); setNbtData(nbtData); } + /** + * Create a clone of another block. + * + * @param other the other block + */ + public BaseBlock(BaseBlock other) { + this(other.getId(), other.getData(), other.getNbtData()); + } + /** * Get the ID of the block. * * @return ID (between 0 and {@link #MAX_ID}) */ + @Override public int getId() { return id; } @@ -138,6 +148,7 @@ public class BaseBlock extends Block implements TileEntityBlock { * * @param id block id (between 0 and {@link #MAX_ID}). */ + @Override public void setId(int id) { internalSetId(id); } @@ -147,6 +158,7 @@ public class BaseBlock extends Block implements TileEntityBlock { * * @return data value (0-15) */ + @Override public int getData() { return data; } @@ -175,6 +187,7 @@ public class BaseBlock extends Block implements TileEntityBlock { * * @param data block data value (between 0 and {@link #MAX_DATA}). */ + @Override public void setData(int data) { internalSetData(data); } @@ -187,6 +200,7 @@ public class BaseBlock extends Block implements TileEntityBlock { * @see #setId(int) * @see #setData(int) */ + @Override public void setIdAndData(int id, int data) { setId(id); setData(data); @@ -198,6 +212,7 @@ public class BaseBlock extends Block implements TileEntityBlock { * * @return true if the data value is -1 */ + @Override public boolean hasWildcardData() { return getData() == -1; } @@ -227,7 +242,7 @@ public class BaseBlock extends Block implements TileEntityBlock { } @Override - public void setNbtData(CompoundTag nbtData) throws DataException { + public void setNbtData(CompoundTag nbtData) { this.nbtData = nbtData; } diff --git a/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java b/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java index fcc9f0a32..d5547e661 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java @@ -19,17 +19,18 @@ package com.sk89q.worldedit.blocks; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTUtils; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.world.DataException; +import com.sk89q.worldedit.world.storage.InvalidFormatException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Represents a chest block. @@ -78,7 +79,7 @@ public class ChestBlock extends ContainerBlock { } @Override - public void setNbtData(CompoundTag rootTag) throws DataException { + public void setNbtData(CompoundTag rootTag) { if (rootTag == null) { return; } @@ -87,19 +88,25 @@ public class ChestBlock extends ContainerBlock { Tag t = values.get("id"); if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Chest")) { - throw new DataException("'Chest' tile entity expected"); + throw new RuntimeException("'Chest' tile entity expected"); } List items = new ArrayList(); - - for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) { - if (!(tag instanceof CompoundTag)) { - throw new DataException("CompoundTag expected as child tag of Chest's Items"); + + try { + for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) { + if (!(tag instanceof CompoundTag)) { + throw new RuntimeException("CompoundTag expected as child tag of Chest's Items"); + } + + items.add((CompoundTag) tag); } - items.add((CompoundTag) tag); + setItems(deserializeInventory(items)); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } catch (DataException e) { + throw new RuntimeException(e); } - - setItems(deserializeInventory(items)); } } diff --git a/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java b/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java index 0608e4935..ea1392924 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java @@ -19,11 +19,6 @@ package com.sk89q.worldedit.blocks; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTUtils; @@ -31,6 +26,11 @@ import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.world.DataException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Represents dispensers. * @@ -79,27 +79,31 @@ public class DispenserBlock extends ContainerBlock { } @Override - public void setNbtData(CompoundTag rootTag) throws DataException { - if (rootTag == null) { - return; - } - - Map values = rootTag.getValue(); - - Tag t = values.get("id"); - if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Trap")) { - throw new DataException("'Trap' tile entity expected"); - } - - List items = new ArrayList(); - for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) { - if (!(tag instanceof CompoundTag)) { - throw new DataException("CompoundTag expected as child tag of Trap Items"); + public void setNbtData(CompoundTag rootTag) { + try { + if (rootTag == null) { + return; } - items.add((CompoundTag) tag); - } + Map values = rootTag.getValue(); - setItems(deserializeInventory(items)); + Tag t = values.get("id"); + if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Trap")) { + throw new DataException("'Trap' tile entity expected"); + } + + List items = new ArrayList(); + for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) { + if (!(tag instanceof CompoundTag)) { + throw new DataException("CompoundTag expected as child tag of Trap Items"); + } + + items.add((CompoundTag) tag); + } + + setItems(deserializeInventory(items)); + } catch (DataException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java b/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java index db4d3e210..24e241dbd 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java @@ -19,11 +19,6 @@ package com.sk89q.worldedit.blocks; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTUtils; @@ -32,6 +27,11 @@ import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.world.DataException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Represents a furnace block. * @@ -125,40 +125,43 @@ public class FurnaceBlock extends ContainerBlock { } @Override - public void setNbtData(CompoundTag rootTag) throws DataException { + public void setNbtData(CompoundTag rootTag) { if (rootTag == null) { return; } - - Map values = rootTag.getValue(); - Tag t = values.get("id"); - if (!(t instanceof StringTag) - || !((StringTag) t).getValue().equals("Furnace")) { - throw new DataException("'Furnace' tile entity expected"); - } + try { + Map values = rootTag.getValue(); - ListTag items = NBTUtils.getChildTag(values, "Items", ListTag.class); - - List compound = new ArrayList(); - - for (Tag tag : items.getValue()) { - if (!(tag instanceof CompoundTag)) { - throw new DataException( - "CompoundTag expected as child tag of Furnace Items"); + Tag t = values.get("id"); + if (!(t instanceof StringTag) + || !((StringTag) t).getValue().equals("Furnace")) { + throw new RuntimeException("'Furnace' tile entity expected"); } - compound.add((CompoundTag) tag); - } - setItems(deserializeInventory(compound)); - t = values.get("BurnTime"); - if (t instanceof ShortTag) { - burnTime = ((ShortTag) t).getValue(); - } + ListTag items = NBTUtils.getChildTag(values, "Items", ListTag.class); - t = values.get("CookTime"); - if (t instanceof ShortTag) { - cookTime = ((ShortTag) t).getValue(); + List compound = new ArrayList(); + + for (Tag tag : items.getValue()) { + if (!(tag instanceof CompoundTag)) { + throw new RuntimeException("CompoundTag expected as child tag of Furnace Items"); + } + compound.add((CompoundTag) tag); + } + setItems(deserializeInventory(compound)); + + t = values.get("BurnTime"); + if (t instanceof ShortTag) { + burnTime = ((ShortTag) t).getValue(); + } + + t = values.get("CookTime"); + if (t instanceof ShortTag) { + cookTime = ((ShortTag) t).getValue(); + } + } catch (DataException e) { + throw new RuntimeException(e); } } } diff --git a/src/main/java/com/sk89q/worldedit/blocks/LazyBlock.java b/src/main/java/com/sk89q/worldedit/blocks/LazyBlock.java index 591744fac..bf9ad5d19 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/LazyBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/LazyBlock.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.blocks; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.extent.Extent; import static com.google.common.base.Preconditions.checkNotNull; @@ -88,17 +87,13 @@ public class LazyBlock extends BaseBlock { public CompoundTag getNbtData() { if (!loaded) { BaseBlock loadedBlock = extent.getBlock(position); - try { - super.setNbtData(loadedBlock.getNbtData()); - } catch (DataException e) { - throw new RuntimeException(e); - } + super.setNbtData(loadedBlock.getNbtData()); } return super.getNbtData(); } @Override - public void setNbtData(CompoundTag nbtData) throws DataException { + public void setNbtData(CompoundTag nbtData) { throw new UnsupportedOperationException("This object is immutable"); } diff --git a/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java index 0004f4210..ed38b5bc8 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java @@ -19,9 +19,13 @@ package com.sk89q.worldedit.blocks; -import com.sk89q.jnbt.*; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.NBTUtils; +import com.sk89q.jnbt.ShortTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.MobType; -import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.storage.InvalidFormatException; import java.util.HashMap; @@ -153,7 +157,7 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock { } @Override - public void setNbtData(CompoundTag rootTag) throws DataException { + public void setNbtData(CompoundTag rootTag) { if (rootTag == null) { return; } @@ -162,11 +166,18 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock { Tag t = values.get("id"); if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("MobSpawner")) { - throw new DataException("'MobSpawner' tile entity expected"); + throw new RuntimeException("'MobSpawner' tile entity expected"); } - StringTag mobTypeTag = NBTUtils.getChildTag(values, "EntityId", StringTag.class); - ShortTag delayTag = NBTUtils.getChildTag(values, "Delay", ShortTag.class); + StringTag mobTypeTag; + ShortTag delayTag; + + try { + mobTypeTag = NBTUtils.getChildTag(values, "EntityId", StringTag.class); + delayTag = NBTUtils.getChildTag(values, "Delay", ShortTag.class); + } catch (InvalidFormatException ignored) { + throw new RuntimeException("Invalid mob spawner data: no EntityId and/or no Delay"); + } this.mobType = mobTypeTag.getValue(); this.delay = delayTag.getValue(); diff --git a/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java b/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java index 19d3dc150..32e1cdb18 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java @@ -19,14 +19,13 @@ package com.sk89q.worldedit.blocks; -import java.util.HashMap; -import java.util.Map; - import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.world.DataException; + +import java.util.HashMap; +import java.util.Map; /** * A note block. @@ -102,7 +101,7 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock { } @Override - public void setNbtData(CompoundTag rootTag) throws DataException { + public void setNbtData(CompoundTag rootTag) { if (rootTag == null) { return; } @@ -112,9 +111,8 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock { Tag t; t = values.get("id"); - if (!(t instanceof StringTag) - || !((StringTag) t).getValue().equals("Music")) { - throw new DataException("'Music' tile entity expected"); + if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Music")) { + throw new RuntimeException("'Music' tile entity expected"); } t = values.get("note"); diff --git a/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java b/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java index 8afff7001..e4d36c0d2 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java @@ -19,13 +19,12 @@ package com.sk89q.worldedit.blocks; -import java.util.HashMap; -import java.util.Map; - import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.world.DataException; + +import java.util.HashMap; +import java.util.Map; /** * Represents a sign block. @@ -104,7 +103,7 @@ public class SignBlock extends BaseBlock implements TileEntityBlock { } @Override - public void setNbtData(CompoundTag rootTag) throws DataException { + public void setNbtData(CompoundTag rootTag) { if (rootTag == null) { return; } @@ -116,9 +115,8 @@ public class SignBlock extends BaseBlock implements TileEntityBlock { text = new String[] { "", "", "", "" }; t = values.get("id"); - if (!(t instanceof StringTag) - || !((StringTag) t).getValue().equals("Sign")) { - throw new DataException("'Sign' tile entity expected"); + if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Sign")) { + throw new RuntimeException("'Sign' tile entity expected"); } t = values.get("Text1"); diff --git a/src/main/java/com/sk89q/worldedit/blocks/SkullBlock.java b/src/main/java/com/sk89q/worldedit/blocks/SkullBlock.java index 02ab5ac6e..981a339ec 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/SkullBlock.java +++ b/src/main/java/com/sk89q/worldedit/blocks/SkullBlock.java @@ -19,14 +19,13 @@ package com.sk89q.worldedit.blocks; -import java.util.HashMap; -import java.util.Map; - import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.world.DataException; + +import java.util.HashMap; +import java.util.Map; /** * A skull block. @@ -165,7 +164,7 @@ public class SkullBlock extends BaseBlock implements TileEntityBlock { } @Override - public void setNbtData(CompoundTag rootTag) throws DataException { + public void setNbtData(CompoundTag rootTag) { if (rootTag == null) { return; } @@ -175,9 +174,8 @@ public class SkullBlock extends BaseBlock implements TileEntityBlock { Tag t; t = values.get("id"); - if (!(t instanceof StringTag) - || !((StringTag) t).getValue().equals("Skull")) { - throw new DataException("'Skull' tile entity expected"); + if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Skull")) { + throw new RuntimeException("'Skull' tile entity expected"); } t = values.get("SkullType"); diff --git a/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index f954e26d8..2d9739dd0 100644 --- a/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -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()); diff --git a/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index ffc765095..acbb1cfcc 100644 --- a/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -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( diff --git a/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index 61ea46fb8..6198ddb43 100644 --- a/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -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( diff --git a/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 20cfba116..23e13cc3c 100644 --- a/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -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> 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())); diff --git a/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java b/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java index ef5fffbcc..e200fcb66 100644 --- a/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java +++ b/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java @@ -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); } } diff --git a/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java b/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java new file mode 100644 index 000000000..bce5511aa --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java @@ -0,0 +1,160 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Location; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Stores block data as a multi-dimensional array of {@link BaseBlock}s and + * other data as lists or maps. + */ +public class BlockArrayClipboard implements Clipboard { + + private final Region region; + private Vector offset = new Vector(); + private final BaseBlock[][][] blocks; + private final List entities = new ArrayList(); + + /** + * Create a new instance. + * + * @param region the bounding region + */ + public BlockArrayClipboard(Region region) { + checkNotNull(region); + checkNotNull(offset); + this.region = region.clone(); + + Vector dimensions = getDimensions(); + blocks = new BaseBlock[dimensions.getBlockX()][dimensions.getBlockY()][dimensions.getBlockZ()]; + } + + @Override + public Region getRegion() { + return region.clone(); + } + + @Override + public Vector getOffset() { + return offset; + } + + @Override + public void setOffset(Vector offset) { + checkNotNull(offset); + this.offset = offset; + } + + /** + * Get the dimensions of the copy, which is at minimum (1, 1, 1). + * + * @return the dimensions + */ + private Vector getDimensions() { + return region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); + } + + @Override + public Vector getMinimumPoint() { + return region.getMinimumPoint(); + } + + @Override + public Vector getMaximumPoint() { + return region.getMaximumPoint(); + } + + @Override + public List getEntities() { + return new ArrayList(entities); + } + + @Nullable + @Override + public Entity createEntity(Location location, BaseEntity entity) { + ClipboardEntity ret = new ClipboardEntity(location, entity); + entities.add(ret); + return ret; + } + + @Override + public BaseBlock getBlock(Vector position) { + if (region.contains(position)) { + Vector v = position.subtract(region.getMinimumPoint()); + BaseBlock block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()]; + if (block != null) { + return new BaseBlock(block); + } + } + + return new BaseBlock(BlockID.AIR); + } + + @Override + public BaseBlock getLazyBlock(Vector position) { + return getBlock(position); + } + + @Override + public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException { + if (region.contains(position)) { + Vector v = position.subtract(region.getMinimumPoint()); + blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()] = new BaseBlock(block); + return true; + } else { + return false; + } + } + + @Nullable + @Override + public Operation commit() { + return null; + } + + /** + * Stores entity data. + */ + private class ClipboardEntity extends StoredEntity { + ClipboardEntity(Location location, BaseEntity entity) { + super(location, entity); + } + + @Override + public boolean remove() { + return entities.remove(this); + } + } + +} diff --git a/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java b/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java new file mode 100644 index 000000000..a8e4f27b6 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java @@ -0,0 +1,58 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.regions.Region; + +/** + * Specifies an object that implements something suitable as a "clipboard." + */ +public interface Clipboard extends Extent { + + /** + * Get the bounding region of this extent. + *

+ * Implementations should return a copy of the region. + * + * @return the bounding region + */ + Region getRegion(); + + /** + * Get the offset at which the area was copied from. + *

+ * The offset is not utilized by clipboards but it can be used + * to store, for example, the relative location from which the copy + * was made. + * + * @return the offset + */ + Vector getOffset(); + + /** + * Set the offset at which the area was copied from. + * + * @param offset the offset + */ + void setOffset(Vector offset); + +} diff --git a/src/main/java/com/sk89q/worldedit/extent/clipboard/StoredEntity.java b/src/main/java/com/sk89q/worldedit/extent/clipboard/StoredEntity.java new file mode 100644 index 000000000..a38d2d412 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/extent/clipboard/StoredEntity.java @@ -0,0 +1,76 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extent.clipboard; + +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.util.Location; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * An implementation of {@link Entity} that stores a {@link BaseEntity} with it. + *

+ * Calls to {@link #getState()} return a clone. + */ +abstract class StoredEntity implements Entity { + + private final Location location; + private final BaseEntity entity; + + /** + * Create a new instance. + * + * @param location the location + * @param entity the entity (which will be copied) + */ + StoredEntity(Location location, BaseEntity entity) { + checkNotNull(location); + checkNotNull(entity); + this.location = location; + this.entity = new BaseEntity(entity); + } + + /** + * Get the entity state. This is not a copy. + * + * @return the entity + */ + BaseEntity getEntity() { + return entity; + } + + @Override + public BaseEntity getState() { + return new BaseEntity(entity); + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public Extent getExtent() { + return location.getExtent(); + } + +} diff --git a/src/main/java/com/sk89q/worldedit/function/pattern/ClipboardPattern.java b/src/main/java/com/sk89q/worldedit/function/pattern/ClipboardPattern.java index 21df293d5..c16718330 100644 --- a/src/main/java/com/sk89q/worldedit/function/pattern/ClipboardPattern.java +++ b/src/main/java/com/sk89q/worldedit/function/pattern/ClipboardPattern.java @@ -19,21 +19,18 @@ package com.sk89q.worldedit.function.pattern; -import com.sk89q.worldedit.CuboidClipboard; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import static com.google.common.base.Preconditions.checkNotNull; /** - * A pattern that reads from {@link CuboidClipboard}. - * - * @deprecated May be removed without notice, but there is no direct replacement yet + * A pattern that reads from {@link Clipboard}. */ -@Deprecated public class ClipboardPattern extends AbstractPattern { - private final CuboidClipboard clipboard; + private final Clipboard clipboard; private final Vector size; /** @@ -41,10 +38,10 @@ public class ClipboardPattern extends AbstractPattern { * * @param clipboard the clipboard */ - public ClipboardPattern(CuboidClipboard clipboard) { + public ClipboardPattern(Clipboard clipboard) { checkNotNull(clipboard); this.clipboard = clipboard; - this.size = clipboard.getSize(); + this.size = clipboard.getMaximumPoint().subtract(clipboard.getMinimumPoint()).add(1, 1, 1); } @Override @@ -53,7 +50,7 @@ public class ClipboardPattern extends AbstractPattern { int yp = Math.abs(position.getBlockY()) % size.getBlockY(); int zp = Math.abs(position.getBlockZ()) % size.getBlockZ(); - return clipboard.getPoint(new Vector(xp, yp, zp)); + return clipboard.getBlock(clipboard.getMinimumPoint().add(new Vector(xp, yp, zp))); } }