diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/LocalBlockVectorSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/LocalBlockVectorSet.java index 15abd874c..e1c83573f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/LocalBlockVectorSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/LocalBlockVectorSet.java @@ -257,12 +257,21 @@ public class LocalBlockVectorSet implements Set { @Override public boolean containsAll(Collection c) { - return c.stream().allMatch(this::contains); + for (Object o : c) { + if (!contains(o)) { + return false; + } + } + return true; } @Override public boolean addAll(Collection c) { - return c.stream().map(this::add).reduce(false, (a, b) -> a || b); + boolean result = false; + for (BlockVector3 v : c) { + result |= add(v); + } + return result; } @Override @@ -290,7 +299,11 @@ public class LocalBlockVectorSet implements Set { @Override public boolean removeAll(Collection c) { - return c.stream().map(this::remove).reduce(false, (a, b) -> a || b); + boolean result = false; + for (Object o : c) { + result |= remove(o); + } + return result; } public void forEach(BlockVectorSetVisitor visitor) { diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java index 0a2b3353e..6b30e85c1 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTOutputStream.java @@ -19,6 +19,8 @@ package com.sk89q.jnbt; +import com.boydti.fawe.object.io.LittleEndianOutputStream; + import static com.google.common.base.Preconditions.checkNotNull; import java.io.Closeable; @@ -66,6 +68,15 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da return os; } + /** + * Use a little endian output stream + */ + public void setLittleEndian() { + if (!(os instanceof LittleEndianOutputStream)) { + this.os = new LittleEndianOutputStream((OutputStream) os); + } + } + /** * Writes a tag. * @@ -79,11 +90,7 @@ public final class NBTOutputStream extends OutputStream implements Closeable, Da checkNotNull(tag); int type = NBTUtils.getTypeCode(tag.getClass()); - byte[] nameBytes = name.getBytes(NBTConstants.CHARSET); - - os.writeByte(type); - os.writeShort(nameBytes.length); - os.write(nameBytes); + writeNamedTagName(name, type); if (type == NBTConstants.TYPE_END) { throw new IOException("Named TAG_End not permitted."); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index 74dd69885..449e86676 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -192,20 +192,11 @@ public class BiomeCommands extends MethodCommands { Collections.sort(distribution); for (Countable c : distribution) { BiomeData data = biomeRegistry.getData(c.getID()); - String str; - if (data == null) { - str = String.format("%-7s (%.3f%%) %s #%d", - String.valueOf(c.getAmount()), - c.getAmount() / (double) size * 100, - "Unknown", - c.getID().getInternalId()); - } else { - str = String.format("%-7s (%.3f%%) %s #%d", - String.valueOf(c.getAmount()), - c.getAmount() / (double) size * 100, - data.getName(), - c.getID().getInternalId()); - } + String str = String.format("%-7s (%.3f%%) %s #%d", + String.valueOf(c.getAmount()), + c.getAmount() / (double) size * 100, + data == null ? "Unknown" : data.getName(), + c.getID().getInternalId()); player.print(str); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java index 5e644fd86..9f42647db 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java @@ -68,11 +68,10 @@ public class AreaPickaxe implements BlockTool { for (int x = ox - range; x <= ox + range; ++x) { for (int z = oz - range; z <= oz + range; ++z) { for (int y = oy + range; y >= oy - range; --y) { - BlockVector3 pos = BlockVector3.at(x, y, z); - if (editSession.getLazyBlock(pos).getBlockType() != initialType) { + if (editSession.getLazyBlock(x, y, z).getBlockType() != initialType) { continue; } - editSession.setBlock(pos, BlockTypes.AIR.getDefaultState()); + editSession.setBlock(x, y, z, BlockTypes.AIR.getDefaultState()); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index 01c1e5240..49ac534bb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -25,9 +25,11 @@ import com.boydti.fawe.jnbt.anvil.generator.OreGen; import com.boydti.fawe.jnbt.anvil.generator.Resource; import com.boydti.fawe.jnbt.anvil.generator.SchemGen; +import com.boydti.fawe.object.clipboard.WorldCopyClipboard; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.pattern.Pattern; @@ -408,4 +410,17 @@ public interface Extent extends InputExtent, OutputExtent { default int getMaxY() { return 255; } + + /** + * Lazily copy a region + * + * @param region + * @return + */ + default BlockArrayClipboard lazyCopy(Region region) { + WorldCopyClipboard faweClipboard = new WorldCopyClipboard(this, region); + BlockArrayClipboard weClipboard = new BlockArrayClipboard(region, faweClipboard); + weClipboard.setOrigin(region.getMinimumPoint()); + return weClipboard; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java index 025bb76d9..61b3b3543 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java @@ -33,6 +33,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.session.ClipboardHolder; import java.io.File; import java.io.FileInputStream; @@ -111,7 +112,7 @@ public interface ClipboardFormat { * @param in * @throws IOException */ - default void hold(Player player, URI uri, InputStream in) throws IOException { + default URIClipboardHolder hold(Player player, URI uri, InputStream in) throws IOException { checkNotNull(player); checkNotNull(uri); checkNotNull(in); @@ -125,6 +126,7 @@ public interface ClipboardFormat { clipboard = reader.read(player.getUniqueId()); URIClipboardHolder holder = new URIClipboardHolder(uri, clipboard); session.setClipboard(holder); + return holder; } default Schematic load(File file) throws IOException { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicWriter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicWriter.java index 9322bc50a..10f953cd5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicWriter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicWriter.java @@ -143,11 +143,10 @@ public class SpongeSchematicWriter implements ClipboardWriter { @Override public > void run(int x, int y, int z, B block) { try { - boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); - if (hasNbt) { - if (block.getNbtData() != null) { - BaseBlock localBlock = (BaseBlock) block; - Map values = localBlock.getNbtData().getValue(); + if (block.hasNbtData()) { + CompoundTag nbt = block.getNbtData(); + if (nbt != null) { + Map values = nbt.getValue(); values.remove("id"); // Remove 'id' if it exists. We want 'Id' @@ -164,7 +163,7 @@ public class SpongeSchematicWriter implements ClipboardWriter { z })); numTiles[0]++; - tilesOut.writeTagPayload(localBlock.getNbtData()); + tilesOut.writeTagPayload(block.getNbtData()); } } int ordinal = block.getOrdinal(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java index ad75ed911..ecb270c6d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/legacycompat/SignCompatibilityHandler.java @@ -26,6 +26,7 @@ import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.world.block.BlockID; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; @@ -35,7 +36,13 @@ public class SignCompatibilityHandler implements NBTCompatibilityHandler { @Override public > boolean isAffectedBlock(B block) { - return block.getBlockType() == BlockTypes.SIGN || block.getBlockType() == BlockTypes.WALL_SIGN; + switch (block.getBlockType().getInternalId()) { + case BlockID.SIGN: + case BlockID.WALL_SIGN: + return true; + default: + return false; + } } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java index c6b7d3552..c6e508058 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/inventory/BlockBagExtent.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.extent.inventory; +import com.boydti.fawe.object.exception.FaweException; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; @@ -26,17 +27,23 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; + /** * Applies a {@link BlockBag} to operations. */ public class BlockBagExtent extends AbstractDelegateExtent { - private Map missingBlocks = new HashMap<>(); + private final boolean mine; + private int[] missingBlocks = new int[BlockTypes.size()]; private BlockBag blockBag; /** @@ -45,9 +52,15 @@ public class BlockBagExtent extends AbstractDelegateExtent { * @param extent the extent * @param blockBag the block bag */ - public BlockBagExtent(Extent extent, @Nullable BlockBag blockBag) { + public BlockBagExtent(Extent extent, @Nonnull BlockBag blockBag) { + this(extent, blockBag, false); + } + + public BlockBagExtent(Extent extent, @Nonnull BlockBag blockBag, boolean mine) { super(extent); + checkNotNull(blockBag); this.blockBag = blockBag; + this.mine = mine; } /** @@ -75,9 +88,15 @@ public class BlockBagExtent extends AbstractDelegateExtent { * @return a map of missing blocks */ public Map popMissing() { - Map missingBlocks = this.missingBlocks; - this.missingBlocks = new HashMap<>(); - return missingBlocks; + HashMap map = new HashMap<>(); + for (int i = 0; i < missingBlocks.length; i++) { + int count = missingBlocks[i]; + if (count > 0) { + map.put(BlockTypes.get(i), count); + } + } + Arrays.fill(missingBlocks, 0); + return map; } @Override @@ -95,21 +114,18 @@ public class BlockBagExtent extends AbstractDelegateExtent { try { blockBag.fetchPlacedBlock(block.toImmutableState()); } catch (UnplaceableBlockException e) { - return false; + throw new FaweException.FaweBlockBagException(); } catch (BlockBagException e) { - if (!missingBlocks.containsKey(block.getBlockType())) { - missingBlocks.put(block.getBlockType(), 1); - } else { - missingBlocks.put(block.getBlockType(), missingBlocks.get(block.getBlockType()) + 1); - } - return false; + missingBlocks[block.getBlockType().getInternalId()]++; + throw new FaweException.FaweBlockBagException(); } } - - if (!existing.getBlockType().getMaterial().isAir()) { - try { - blockBag.storeDroppedBlock(existing); - } catch (BlockBagException ignored) { + if (mine) { + if (!existing.getBlockType().getMaterial().isAir()) { + try { + blockBag.storeDroppedBlock(existing); + } catch (BlockBagException ignored) { + } } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java index 043c3345f..3d1fc566b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java @@ -85,17 +85,27 @@ public class BlockTransformExtent extends ResettableExtent { private static long combine(Direction... directions) { - return Arrays.stream(directions).mapToLong(dir -> (1L << dir.ordinal())).reduce(0, (a, b) -> a | b); + long mask = 0; + for (Direction dir : directions) { + mask = mask | (1L << dir.ordinal()); + } + return mask; } private static long[] adapt(Direction... dirs) { long[] arr = new long[dirs.length]; - Arrays.setAll(arr, i -> 1L << dirs[i].ordinal()); + for (int i = 0; i < arr.length; i++) { + arr[i] = 1L << dirs[i].ordinal(); + } return arr; } private static long[] adapt(Long... dirs) { - return Arrays.stream(dirs).mapToLong(dir -> dir).toArray(); + long[] arr = new long[dirs.length]; + for (int i = 0; i < arr.length; i++) { + arr[i] = dirs[i]; + } + return arr; } private static long[] getDirections(AbstractProperty property) { @@ -209,7 +219,9 @@ public class BlockTransformExtent extends ResettableExtent { } private static long notIndex(long mask, int... indexes) { - mask |= Arrays.stream(indexes).mapToLong(index -> (1L << (index + values().length))).reduce(0, (a, b) -> a | b); + for (int index : indexes) { + mask = mask | (1L << (index + values().length)); + } return mask; } @@ -421,8 +433,7 @@ public class BlockTransformExtent extends ResettableExtent { * @return the same block */ public static > B transform(B block, Transform transform) { - checkNotNull(block); - checkNotNull(transform); + // performance critical BlockState state = block.toImmutableState(); int transformedId = transformState(state, transform); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java index c5af9a99d..0c994e0de 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java @@ -260,11 +260,7 @@ public class BaseBlock implements BlockStateHolder { @Override public int hashCode() { - int ret = toImmutableState().hashCode() << 3; - if (hasNbtData()) { - ret += getNbtData().hashCode(); - } - return ret; + return getOrdinal(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java index fc1438784..4b896af0e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java @@ -849,4 +849,8 @@ public final class ItemTypes { public static int size() { return ItemType.REGISTRY.size(); } + + public static Collection values() { + return ItemType.REGISTRY.values(); + } }