Further work on BlockState transition

This commit is contained in:
Matthew Miller
2018-06-18 22:51:21 +10:00
parent e99190225e
commit 484687a49d
76 changed files with 2911 additions and 10010 deletions

View File

@ -23,6 +23,9 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.operation.Operation;
@ -64,17 +67,22 @@ public abstract class AbstractDelegateExtent implements Extent {
}
@Override
public BaseBlock getBlock(Vector position) {
public BlockState getBlock(Vector position) {
return extent.getBlock(position);
}
@Override
public BaseBlock getLazyBlock(Vector position) {
public LazyBlock getLazyBlock(Vector position) {
return extent.getLazyBlock(position);
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public BaseBlock getFullBlock(Vector position) {
return extent.getFullBlock(position);
}
@Override
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
return extent.setBlock(location, block);
}

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.history.change.BlockChange;
@ -58,8 +59,8 @@ public class ChangeSetExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
BaseBlock previous = getBlock(location);
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
BlockStateHolder previous = getBlock(location);
changeSet.add(new BlockChange(location.toBlockVector(), previous, block));
return super.setBlock(location, block);
}

View File

@ -22,6 +22,9 @@ package com.sk89q.worldedit.extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.biome.BaseBiome;
@ -37,20 +40,14 @@ public interface InputExtent {
* is undefined (an air block could be returned). However, {@code null}
* should <strong>not</strong> be returned.</p>
*
* <p>The returned block is mutable and is a snapshot of the block at the time
* <p>The returned block is immutable and is a snapshot of the block at the time
* of call. It has no position attached to it, so it could be reused in
* {@link Pattern}s and so on.</p>
*
* <p>Calls to this method can actually be quite expensive, so cache results
* whenever it is possible, while being aware of the mutability aspect.
* The cost, however, depends on the implementation and particular extent.
* If only basic information about the block is required, then use of
* {@link #getLazyBlock(Vector)} is recommended.</p>
*
* @param position position of the block
* @return the block
*/
BaseBlock getBlock(Vector position);
BlockState getBlock(Vector position);
/**
* Get a lazy, immutable snapshot of the block at the given location that only
@ -73,7 +70,15 @@ public interface InputExtent {
* @param position position of the block
* @return the block
*/
BaseBlock getLazyBlock(Vector position);
LazyBlock getLazyBlock(Vector position);
/**
* Get a immutable snapshot of the block at the given location.
*
* @param position position of the block
* @return the block
*/
BaseBlock getFullBlock(Vector position);
/**
* Get the biome at the given location.

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.function.mask.Mask;
import static com.google.common.base.Preconditions.checkNotNull;
@ -65,7 +66,7 @@ public class MaskingExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
return mask.test(location) && super.setBlock(location, block);
}

View File

@ -23,6 +23,9 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -70,13 +73,18 @@ public class NullExtent implements Extent {
}
@Override
public BaseBlock getBlock(Vector position) {
return new BaseBlock(BlockTypes.AIR);
public BlockState getBlock(Vector position) {
return BlockTypes.AIR.getDefaultState();
}
@Override
public BaseBlock getLazyBlock(Vector position) {
return new BaseBlock(BlockTypes.AIR);
public LazyBlock getLazyBlock(Vector position) {
return new LazyBlock(BlockTypes.AIR, this, position);
}
@Override
public BaseBlock getFullBlock(Vector position) {
return new BaseBlock(getBlock(position));
}
@Nullable
@ -86,7 +94,7 @@ public class NullExtent implements Extent {
}
@Override
public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector position, BlockStateHolder block) throws WorldEditException {
return false;
}

View File

@ -22,7 +22,7 @@ package com.sk89q.worldedit.extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.world.biome.BaseBiome;
@ -35,8 +35,8 @@ public interface OutputExtent {
/**
* Change the block at the given location to the given block. The operation may
* not tie the given {@link BaseBlock} to the world, so future changes to the
* {@link BaseBlock} do not affect the world until this method is called again.
* not tie the given {@link BlockStateHolder} to the world, so future changes to the
* {@link BlockStateHolder} do not affect the world until this method is called again.
*
* <p>The return value of this method indicates whether the change was probably
* successful. It may not be successful if, for example, the location is out
@ -50,7 +50,7 @@ public interface OutputExtent {
* @return true if the block was successfully set (return value may not be accurate)
* @throws WorldEditException thrown on an error
*/
boolean setBlock(Vector position, BaseBlock block) throws WorldEditException;
boolean setBlock(Vector position, BlockStateHolder block) throws WorldEditException;
/**
* Set the biome.

View File

@ -19,10 +19,13 @@
package com.sk89q.worldedit.extent.buffer;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
@ -37,8 +40,6 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Buffers changes to an {@link Extent} and allows later retrieval for
* actual application of the changes.
@ -48,9 +49,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pattern {
private static final BaseBlock AIR = new BaseBlock(BlockTypes.AIR);
private static final BlockState AIR = BlockTypes.AIR.getDefaultState();
private final Map<BlockVector, BaseBlock> buffer = new LinkedHashMap<>();
private final Map<BlockVector, BlockStateHolder> buffer = new LinkedHashMap<>();
private final Mask mask;
private Vector min = null;
private Vector max = null;
@ -79,7 +80,7 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
// Update minimum
if (min == null) {
min = location;
@ -104,8 +105,8 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
}
@Override
public BaseBlock apply(Vector pos) {
BaseBlock block = buffer.get(pos.toBlockVector());
public BlockStateHolder apply(Vector pos) {
BlockStateHolder block = buffer.get(pos.toBlockVector());
if (block != null) {
return block;
} else {

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extent.cache;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
@ -43,13 +44,13 @@ public class LastAccessExtentCache extends AbstractDelegateExtent {
}
@Override
public BaseBlock getLazyBlock(Vector position) {
public LazyBlock getLazyBlock(Vector position) {
BlockVector blockVector = position.toBlockVector();
CachedBlock lastBlock = this.lastBlock;
if (lastBlock != null && lastBlock.position.equals(blockVector)) {
return lastBlock.block;
} else {
BaseBlock block = super.getLazyBlock(position);
LazyBlock block = super.getLazyBlock(position);
this.lastBlock = new CachedBlock(blockVector, block);
return block;
}
@ -57,9 +58,9 @@ public class LastAccessExtentCache extends AbstractDelegateExtent {
private static class CachedBlock {
private final BlockVector position;
private final BaseBlock block;
private final LazyBlock block;
private CachedBlock(BlockVector position, BaseBlock block) {
private CachedBlock(BlockVector position, LazyBlock block) {
this.position = position;
this.block = block;
}

View File

@ -23,6 +23,9 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -45,8 +48,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class BlockArrayClipboard implements Clipboard {
private final Region region;
private Vector origin = new Vector();
private final BaseBlock[][][] blocks;
private Vector origin;
private final BlockStateHolder[][][] blocks;
private final List<ClipboardEntity> entities = new ArrayList<>();
/**
@ -120,12 +123,38 @@ public class BlockArrayClipboard implements Clipboard {
}
@Override
public BaseBlock getBlock(Vector position) {
public BlockState getBlock(Vector position) {
if (region.contains(position)) {
Vector v = position.subtract(region.getMinimumPoint());
BaseBlock block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()];
BlockStateHolder block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()];
if (block != null) {
return new BaseBlock(block);
if (block instanceof BlockState) {
return (BlockState) block;
} else if (block instanceof BaseBlock) {
return ((BaseBlock) block).getState();
}
}
}
return BlockTypes.AIR.getDefaultState();
}
@Override
public LazyBlock getLazyBlock(Vector position) {
return new LazyBlock(getBlock(position), null, position);
}
@Override
public BaseBlock getFullBlock(Vector position) {
if (region.contains(position)) {
Vector v = position.subtract(region.getMinimumPoint());
BlockStateHolder block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()];
if (block != null) {
if (block instanceof BlockState) {
return new BaseBlock((BlockState) block);
} else if (block instanceof BaseBlock) {
return (BaseBlock) block;
}
}
}
@ -133,15 +162,10 @@ public class BlockArrayClipboard implements Clipboard {
}
@Override
public BaseBlock getLazyBlock(Vector position) {
return getBlock(position);
}
@Override
public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector position, BlockStateHolder block) throws WorldEditException {
if (region.contains(position)) {
Vector v = position.subtract(region.getMinimumPoint());
blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()] = new BaseBlock(block);
blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()] = block;
return true;
} else {
return false;

View File

@ -21,7 +21,6 @@ package com.sk89q.worldedit.extent.clipboard.io;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import javax.annotation.Nullable;
import java.io.DataInputStream;
@ -38,7 +37,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import static com.google.common.base.Preconditions.checkNotNull;
@ -59,8 +57,7 @@ public enum ClipboardFormat {
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
NBTOutputStream nbtStream = new NBTOutputStream(new GZIPOutputStream(outputStream));
return new SchematicWriter(nbtStream);
throw new UnsupportedOperationException("This clipboard format is deprecated.");
}
@Override

View File

@ -1,218 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extent.clipboard.io;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
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.clipboard.Clipboard;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Writes schematic files based that are compatible with MCEdit and other editors.
*/
public class SchematicWriter implements ClipboardWriter {
private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE;
private final NBTOutputStream outputStream;
/**
* Create a new schematic writer.
*
* @param outputStream the output stream to write to
*/
public SchematicWriter(NBTOutputStream outputStream) {
checkNotNull(outputStream);
this.outputStream = outputStream;
}
@Override
public void write(Clipboard clipboard, WorldData data) throws IOException {
Region region = clipboard.getRegion();
Vector origin = clipboard.getOrigin();
Vector min = region.getMinimumPoint();
Vector offset = min.subtract(origin);
int width = region.getWidth();
int height = region.getHeight();
int length = region.getLength();
if (width > MAX_SIZE) {
throw new IllegalArgumentException("Width of region too large for a .schematic");
}
if (height > MAX_SIZE) {
throw new IllegalArgumentException("Height of region too large for a .schematic");
}
if (length > MAX_SIZE) {
throw new IllegalArgumentException("Length of region too large for a .schematic");
}
// ====================================================================
// Metadata
// ====================================================================
HashMap<String, Tag> schematic = new HashMap<>();
schematic.put("Width", new ShortTag((short) width));
schematic.put("Length", new ShortTag((short) length));
schematic.put("Height", new ShortTag((short) height));
schematic.put("Materials", new StringTag("Alpha"));
schematic.put("WEOriginX", new IntTag(min.getBlockX()));
schematic.put("WEOriginY", new IntTag(min.getBlockY()));
schematic.put("WEOriginZ", new IntTag(min.getBlockZ()));
schematic.put("WEOffsetX", new IntTag(offset.getBlockX()));
schematic.put("WEOffsetY", new IntTag(offset.getBlockY()));
schematic.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
// ====================================================================
// Block handling
// ====================================================================
byte[] blocks = new byte[width * height * length];
byte[] addBlocks = null;
byte[] blockData = new byte[width * height * length];
List<Tag> tileEntities = new ArrayList<>();
for (Vector point : region) {
Vector relative = point.subtract(min);
int x = relative.getBlockX();
int y = relative.getBlockY();
int z = relative.getBlockZ();
int index = y * width * length + z * width + x;
BaseBlock block = clipboard.getBlock(point);
// Save 4096 IDs in an AddBlocks section
if (block.getId() > 255) {
if (addBlocks == null) { // Lazily create section
addBlocks = new byte[(blocks.length >> 1) + 1];
}
addBlocks[index >> 1] = (byte) (((index & 1) == 0) ?
addBlocks[index >> 1] & 0xF0 | (block.getId() >> 8) & 0xF
: addBlocks[index >> 1] & 0xF | ((block.getId() >> 8) & 0xF) << 4);
}
blocks[index] = (byte) block.getId();
blockData[index] = (byte) block.getData();
// Store TileEntity data
CompoundTag rawTag = block.getNbtData();
if (rawTag != null) {
Map<String, Tag> values = new HashMap<>();
for (Entry<String, Tag> entry : rawTag.getValue().entrySet()) {
values.put(entry.getKey(), entry.getValue());
}
values.put("id", new StringTag(block.getNbtId()));
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
CompoundTag tileEntityTag = new CompoundTag(values);
tileEntities.add(tileEntityTag);
}
}
schematic.put("Blocks", new ByteArrayTag(blocks));
schematic.put("Data", new ByteArrayTag(blockData));
schematic.put("TileEntities", new ListTag(CompoundTag.class, tileEntities));
if (addBlocks != null) {
schematic.put("AddBlocks", new ByteArrayTag(addBlocks));
}
// ====================================================================
// Entities
// ====================================================================
List<Tag> entities = new ArrayList<>();
for (Entity entity : clipboard.getEntities()) {
BaseEntity state = entity.getState();
if (state != null) {
Map<String, Tag> values = new HashMap<>();
// Put NBT provided data
CompoundTag rawTag = state.getNbtData();
if (rawTag != null) {
values.putAll(rawTag.getValue());
}
// Store our location data, overwriting any
values.put("id", new StringTag(state.getTypeId()));
values.put("Pos", writeVector(entity.getLocation().toVector(), "Pos"));
values.put("Rotation", writeRotation(entity.getLocation(), "Rotation"));
CompoundTag entityTag = new CompoundTag(values);
entities.add(entityTag);
}
}
schematic.put("Entities", new ListTag(CompoundTag.class, entities));
// ====================================================================
// Output
// ====================================================================
CompoundTag schematicTag = new CompoundTag(schematic);
outputStream.writeNamedTag("Schematic", schematicTag);
}
private Tag writeVector(Vector vector, String name) {
List<DoubleTag> list = new ArrayList<>();
list.add(new DoubleTag(vector.getX()));
list.add(new DoubleTag(vector.getY()));
list.add(new DoubleTag(vector.getZ()));
return new ListTag(DoubleTag.class, list);
}
private Tag writeRotation(Location location, String name) {
List<FloatTag> list = new ArrayList<>();
list.add(new FloatTag(location.getYaw()));
list.add(new FloatTag(location.getPitch()));
return new ListTag(FloatTag.class, list);
}
@Override
public void close() throws IOException {
outputStream.close();
}
}

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extent.inventory;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
@ -79,7 +80,7 @@ public class BlockBagExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector position, BlockStateHolder block) throws WorldEditException {
if (blockBag != null) {
BaseBlock lazyBlock = getExtent().getLazyBlock(position);
int existing = lazyBlock.getBlockType().getLegacyId();

View File

@ -1,57 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extent.logging;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
/**
* An abstract class to implement block loggers and so on with.
*/
public abstract class AbstractLoggingExtent extends AbstractDelegateExtent {
/**
* Create a new instance.
*
* @param extent the extent
*/
protected AbstractLoggingExtent(Extent extent) {
super(extent);
}
/**
* Called when a block is being changed.
*
* @param position the position
* @param newBlock the new block to replace the old one
*/
protected void onBlockChange(Vector position, BaseBlock newBlock) {
}
@Override
public final boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
onBlockChange(position, block);
return super.setBlock(position, block);
}
}

View File

@ -27,6 +27,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
@ -43,9 +44,9 @@ import java.util.*;
*/
public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent {
private TupleArrayList<BlockVector, BaseBlock> stage1 = new TupleArrayList<>();
private TupleArrayList<BlockVector, BaseBlock> stage2 = new TupleArrayList<>();
private TupleArrayList<BlockVector, BaseBlock> stage3 = new TupleArrayList<>();
private TupleArrayList<BlockVector, BlockStateHolder> stage1 = new TupleArrayList<>();
private TupleArrayList<BlockVector, BlockStateHolder> stage2 = new TupleArrayList<>();
private TupleArrayList<BlockVector, BlockStateHolder> stage3 = new TupleArrayList<>();
private boolean enabled;
/**
@ -87,7 +88,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
BaseBlock lazyBlock = getLazyBlock(location);
if (!enabled) {
@ -97,18 +98,18 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
if (BlockType.shouldPlaceLast(block.getBlockType().getLegacyId())) {
// Place torches, etc. last
stage2.put(location.toBlockVector(), block);
return !(lazyBlock.getBlockType() == block.getBlockType() && lazyBlock.getData() == block.getData());
return !(lazyBlock.getBlockType() == block.getBlockType()); // TODO && lazyBlock.getData() == block.getData());
} else if (BlockType.shouldPlaceFinal(block.getBlockType().getLegacyId())) {
// Place signs, reed, etc even later
stage3.put(location.toBlockVector(), block);
return !(lazyBlock.getBlockType() == block.getBlockType() && lazyBlock.getData() == block.getData());
return !(lazyBlock.getBlockType() == block.getBlockType()); // TODO && lazyBlock.getData() == block.getData());
} else if (BlockType.shouldPlaceLast(lazyBlock.getBlockType().getLegacyId())) {
// Destroy torches, etc. first
super.setBlock(location, new BaseBlock(BlockTypes.AIR));
super.setBlock(location, BlockTypes.AIR.getDefaultState());
return super.setBlock(location, block);
} else {
stage1.put(location.toBlockVector(), block);
return !(lazyBlock.getBlockType() == block.getBlockType() && lazyBlock.getData() == block.getData());
return !(lazyBlock.getBlockType() == block.getBlockType()); // TODO && lazyBlock.getData() == block.getData());
}
}
@ -128,8 +129,8 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
Extent extent = getExtent();
final Set<BlockVector> blocks = new HashSet<>();
final Map<BlockVector, BaseBlock> blockTypes = new HashMap<>();
for (Map.Entry<BlockVector, BaseBlock> entry : stage3) {
final Map<BlockVector, BlockStateHolder> blockTypes = new HashMap<>();
for (Map.Entry<BlockVector, BlockStateHolder> entry : stage3) {
final BlockVector pt = entry.getKey();
blocks.add(pt);
blockTypes.put(pt, entry.getValue());
@ -148,10 +149,10 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
assert (blockTypes.containsKey(current));
final BaseBlock baseBlock = blockTypes.get(current);
final BlockStateHolder baseBlock = blockTypes.get(current);
final int type = baseBlock.getBlockType().getLegacyId();
final int data = baseBlock.getData();
// final int data = baseBlock.getData();
switch (type) {
case BlockID.WOODEN_DOOR:
@ -161,13 +162,13 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
case BlockID.DARK_OAK_DOOR:
case BlockID.SPRUCE_DOOR:
case BlockID.IRON_DOOR:
if ((data & 0x8) == 0) {
// Deal with lower door halves being attached to the floor AND the upper half
BlockVector upperBlock = current.add(0, 1, 0).toBlockVector();
if (blocks.contains(upperBlock) && !walked.contains(upperBlock)) {
walked.addFirst(upperBlock);
}
}
// TODO if ((data & 0x8) == 0) {
// // Deal with lower door halves being attached to the floor AND the upper half
// BlockVector upperBlock = current.add(0, 1, 0).toBlockVector();
// if (blocks.contains(upperBlock) && !walked.contains(upperBlock)) {
// walked.addFirst(upperBlock);
// }
// }
break;
case BlockID.MINECART_TRACKS:
@ -183,7 +184,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
break;
}
final PlayerDirection attachment = BlockType.getAttachment(type, data);
final PlayerDirection attachment = BlockType.getAttachment(type, 0); // TODO
if (attachment == null) {
// Block is not attached to anything => we can place it
break;

View File

@ -24,6 +24,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.transform.Transform;
@ -77,24 +80,29 @@ public class BlockTransformExtent extends AbstractDelegateExtent {
* @param reverse true to transform in the opposite direction
* @return the same block
*/
private BaseBlock transformBlock(BaseBlock block, boolean reverse) {
private <T extends BlockStateHolder> T transformBlock(T block, boolean reverse) {
transform(block, reverse ? transform.inverse() : transform, blockRegistry);
return block;
}
@Override
public BaseBlock getBlock(Vector position) {
public BlockState getBlock(Vector position) {
return transformBlock(super.getBlock(position), false);
}
@Override
public BaseBlock getLazyBlock(Vector position) {
public LazyBlock getLazyBlock(Vector position) {
return transformBlock(super.getLazyBlock(position), false);
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
return super.setBlock(location, transformBlock(new BaseBlock(block), true));
public BaseBlock getFullBlock(Vector position) {
return transformBlock(super.getFullBlock(position), false);
}
@Override
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
return super.setBlock(location, transformBlock(block, true));
}
@ -108,7 +116,7 @@ public class BlockTransformExtent extends AbstractDelegateExtent {
* @param registry the registry
* @return the same block
*/
public static BaseBlock transform(BaseBlock block, Transform transform, BlockRegistry registry) {
public static <T extends BlockStateHolder> T transform(T block, Transform transform, BlockRegistry registry) {
return transform(block, transform, registry, block);
}
@ -121,7 +129,7 @@ public class BlockTransformExtent extends AbstractDelegateExtent {
* @param changedBlock the block to change
* @return the changed block
*/
private static BaseBlock transform(BaseBlock block, Transform transform, BlockRegistry registry, BaseBlock changedBlock) {
private static <T extends BlockStateHolder> T transform(T block, Transform transform, BlockRegistry registry, T changedBlock) {
checkNotNull(block);
checkNotNull(transform);
checkNotNull(registry);

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
@ -77,7 +78,7 @@ public class BlockChangeLimiter extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
if (limit >= 0) {
if (count >= limit) {
throw new MaxChangedBlocksException(limit);

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extent.validation;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockType;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
@ -49,7 +50,7 @@ public class DataValidatorExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
final int y = location.getBlockY();
final BlockType type = block.getBlockType();
if (y < 0 || y > world.getMaxY()) {
@ -61,16 +62,7 @@ public class DataValidatorExtent extends AbstractDelegateExtent {
return false;
}
if (block.getData() < 0) {
throw new SevereValidationException("Cannot set a data value that is less than 0");
}
return super.setBlock(location, block);
}
private static class SevereValidationException extends WorldEditException {
private SevereValidationException(String message) {
super(message);
}
}
}

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
@ -52,7 +53,7 @@ public class BlockQuirkExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector position, BlockStateHolder block) throws WorldEditException {
BaseBlock lazyBlock = getExtent().getLazyBlock(position);
int existing = lazyBlock.getBlockType().getLegacyId();

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extent.world;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
@ -61,7 +62,7 @@ public class ChunkLoadingExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
world.checkLoadedChunk(location);
return super.setBlock(location, block);
}

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
@ -84,7 +85,7 @@ public class FastModeExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
if (enabled) {
dirtyChunks.add(new BlockVector2D(location.getBlockX() >> 4, location.getBlockZ() >> 4));
return world.setBlock(location, block, false);

View File

@ -22,6 +22,8 @@ package com.sk89q.worldedit.extent.world;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
@ -79,8 +81,8 @@ public class SurvivalModeExtent extends AbstractDelegateExtent {
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
if (toolUse && block.isAir()) {
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
if (toolUse && block.getBlockType() == BlockTypes.AIR) {
world.simulateBlockMine(location);
return true;
} else {