From bb56a397928047beb23c4f5658838ccbf47f19bd Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Wed, 29 Mar 2017 06:57:01 +1100 Subject: [PATCH] Optimize schem paste + add MCAWriter to anvil --- .../main/java/com/boydti/fawe/FaweCache.java | 5 +- .../com/boydti/fawe/jnbt/NBTStreamer.java | 2 + .../jnbt/anvil/HeightMapMCAGenerator.java | 665 +++++++----------- .../com/boydti/fawe/jnbt/anvil/MCAWriter.java | 183 +++++ .../boydti/fawe/object/brush/ErodeBrush.java | 7 +- .../AbstractDelegateFaweClipboard.java | 3 +- .../clipboard/CPUOptimizedClipboard.java | 13 +- .../clipboard/DiskOptimizedClipboard.java | 77 +- .../fawe/object/clipboard/FaweClipboard.java | 25 +- .../clipboard/MemoryOptimizedClipboard.java | 31 +- .../object/clipboard/OffsetFaweClipboard.java | 13 +- .../object/clipboard/WorldCopyClipboard.java | 69 +- .../object/clipboard/WorldCutClipboard.java | 2 +- .../fawe/object/schematic/Schematic.java | 26 +- .../java/com/sk89q/worldedit/EditSession.java | 13 +- .../com/sk89q/worldedit/blocks/BaseBlock.java | 5 + .../worldedit/blocks/ImmutableBlock.java | 5 + .../blocks/ImmutableDatalessBlock.java | 5 + .../worldedit/blocks/ImmutableNBTBlock.java | 12 + .../extent/clipboard/io/SchematicWriter.java | 18 +- 20 files changed, 628 insertions(+), 551 deletions(-) create mode 100644 core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java create mode 100644 core/src/main/java/com/sk89q/worldedit/blocks/ImmutableNBTBlock.java diff --git a/core/src/main/java/com/boydti/fawe/FaweCache.java b/core/src/main/java/com/boydti/fawe/FaweCache.java index 38497d6e..5efc6305 100644 --- a/core/src/main/java/com/boydti/fawe/FaweCache.java +++ b/core/src/main/java/com/boydti/fawe/FaweCache.java @@ -19,6 +19,7 @@ import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.ImmutableBlock; import com.sk89q.worldedit.blocks.ImmutableDatalessBlock; +import com.sk89q.worldedit.blocks.ImmutableNBTBlock; import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.registry.BundledBlockData; import java.awt.Color; @@ -176,7 +177,9 @@ public class FaweCache { for (int i = 0; i < Character.MAX_VALUE; i++) { int id = i >> 4; int data = i & 0xf; - if (FaweCache.hasData(id)) { + if (FaweCache.hasNBT(id)) { + CACHE_BLOCK[i] = new ImmutableNBTBlock(id, data); + } else if (FaweCache.hasData(id)) { CACHE_BLOCK[i] = new ImmutableBlock(id, data); } else { CACHE_BLOCK[i] = new ImmutableDatalessBlock(id); diff --git a/core/src/main/java/com/boydti/fawe/jnbt/NBTStreamer.java b/core/src/main/java/com/boydti/fawe/jnbt/NBTStreamer.java index 69b83378..f6df7c87 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/NBTStreamer.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/NBTStreamer.java @@ -2,6 +2,8 @@ package com.boydti.fawe.jnbt; import com.boydti.fawe.object.RunnableVal2; import com.sk89q.jnbt.NBTInputStream; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; import java.io.IOException; import java.util.HashMap; diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java index a81c00b9..67ca987e 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java @@ -2,8 +2,6 @@ package com.boydti.fawe.jnbt.anvil; import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.PseudoRandom; -import com.boydti.fawe.object.io.BufferedRandomAccessFile; -import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MutableBlockVector; @@ -22,17 +20,19 @@ import com.sk89q.worldedit.world.registry.WorldData; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.awt.image.BufferedImage; import java.io.File; -import java.io.IOException; import java.util.Arrays; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.TimeUnit; -import java.util.zip.Deflater; -public class HeightMapMCAGenerator implements Extent { +public class HeightMapMCAGenerator extends MCAWriter implements Extent { private final MutableBlockVector mutable = new MutableBlockVector(); - private final ForkJoinPool pool = new ForkJoinPool(); - final Int2ObjectOpenHashMap blocks = new Int2ObjectOpenHashMap<>(); + private final ThreadLocal indexStore = new ThreadLocal() { + @Override + protected int[] initialValue() { + return new int[256]; + } + }; + + private final Int2ObjectOpenHashMap blocks = new Int2ObjectOpenHashMap<>(); private final byte[] heights; private final byte[] biomes; @@ -40,11 +40,6 @@ public class HeightMapMCAGenerator implements Extent { private final char[] main; private char[] overlay; - private final File folder; - private final int length; - private final int width; - private final int area; - private boolean modifiedMain = false; public HeightMapMCAGenerator(BufferedImage img, File regionFolder) { @@ -53,17 +48,12 @@ public class HeightMapMCAGenerator implements Extent { } public HeightMapMCAGenerator(int width, int length, File regionFolder) { - if (!regionFolder.exists()) { - regionFolder.mkdirs(); - } - this.folder = regionFolder; - this.width = width; - this.length = length; - this.area = width * length; - heights = new byte[area]; - biomes = new byte[area]; - floor = new char[area]; - main = new char[area]; + super(width, length, regionFolder); + int area = getArea(); + heights = new byte[getArea()]; + biomes = new byte[getArea()]; + floor = new char[getArea()]; + main = new char[getArea()]; char stone = (char) FaweCache.getCombined(1, 0); char grass = (char) FaweCache.getCombined(2, 0); Arrays.fill(main, stone); @@ -72,30 +62,30 @@ public class HeightMapMCAGenerator implements Extent { public void setHeight(BufferedImage img) { int index = 0; - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++, index++){ + for (int z = 0; z < getLength(); z++) { + for (int x = 0; x < getWidth(); x++, index++){ heights[index] = (byte) img.getRGB(x, z); } } } public void addCaves() throws WorldEditException { - CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length)); + CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength())); addCaves(region); } public void addSchems(Mask mask, WorldData worldData, ClipboardHolder[] clipboards, int rarity, boolean rotate) throws WorldEditException{ - CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length)); + CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength())); addSchems(region, mask, worldData, clipboards, rarity, rotate); } public void addOre(Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException { - CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length)); + CuboidRegion region = new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength())); addOre(region, mask, material, size, frequency, rarity, minY, maxY); } public void addDefaultOres(Mask mask) throws WorldEditException { - addOres(new CuboidRegion(new Vector(0, 0, 0), new Vector(width, 255, length)), mask); + addOres(new CuboidRegion(new Vector(0, 0, 0), new Vector(getWidth(), 255, getLength())), mask); } @Override @@ -105,7 +95,7 @@ public class HeightMapMCAGenerator implements Extent { @Override public Vector getMaximumPoint() { - return new Vector(width - 1, 255, length - 1); + return new Vector(getWidth() - 1, 255, getLength() - 1); } @Override @@ -115,7 +105,7 @@ public class HeightMapMCAGenerator implements Extent { @Override public boolean setBiome(Vector2D position, BaseBiome biome) { - int index = position.getBlockZ() * width + position.getBlockX(); + int index = position.getBlockZ() * getWidth() + position.getBlockX(); if (index < 0 || index >= heights.length) return false; biomes[index] = (byte) biome.getId(); return true; @@ -123,14 +113,14 @@ public class HeightMapMCAGenerator implements Extent { @Override public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException { - int index = z * width + x; + int index = z * getWidth() + x; if (index < 0 || index >= heights.length) return false; int height = heights[index] & 0xFF; char combined = (char) FaweCache.getCombined(block); if (y > height) { if (y == height + 1) { if (overlay == null) { - overlay = new char[area]; + overlay = new char[getArea()]; } overlay[index] = combined; return true; @@ -174,7 +164,7 @@ public class HeightMapMCAGenerator implements Extent { @Override public BaseBiome getBiome(Vector2D position) { - int index = position.getBlockZ() * width + position.getBlockX(); + int index = position.getBlockZ() * getWidth() + position.getBlockX(); if (index < 0 || index >= heights.length) return EditSession.nullBiome; return FaweCache.CACHE_BIOME[biomes[index] & 0xFF]; } @@ -191,7 +181,7 @@ public class HeightMapMCAGenerator implements Extent { @Override public BaseBlock getLazyBlock(int x, int y, int z) { - int index = z * width + x; + int index = z * getWidth() + x; if (index < 0 || index >= heights.length) return EditSession.nullBlock; int height = heights[index] & 0xFF; if (y > height) { @@ -232,23 +222,23 @@ public class HeightMapMCAGenerator implements Extent { @Override public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) { - int index = z * width + x; + int index = z * getWidth() + x; if (index < 0 || index >= heights.length) return y; return ((heights[index] & 0xFF) << 3) + (floor[index] & 0xFF) + 1; } @Override public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) { - int index = z * width + x; + int index = z * getWidth() + x; if (index < 0 || index >= heights.length) return y; return heights[index] & 0xFF; } public void setBiome(BufferedImage img, byte biome, boolean white) { - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); int index = 0; - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++, index++){ + for (int z = 0; z < getLength(); z++) { + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { biomes[index] = biome; @@ -258,11 +248,11 @@ public class HeightMapMCAGenerator implements Extent { } private void setOverlay(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); - if (overlay == null) overlay = new char[area]; + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (overlay == null) overlay = new char[getArea()]; int index = 0; - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++, index++){ + for (int z = 0; z < getLength(); z++) { + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { overlay[index] = combined; @@ -272,11 +262,11 @@ public class HeightMapMCAGenerator implements Extent { } private void setMain(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++, index++){ + for (int z = 0; z < getLength(); z++) { + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { main[index] = combined; @@ -286,10 +276,10 @@ public class HeightMapMCAGenerator implements Extent { } private void setFloor(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); int index = 0; - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++, index++){ + for (int z = 0; z < getLength(); z++) { + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { floor[index] = combined; @@ -299,11 +289,11 @@ public class HeightMapMCAGenerator implements Extent { } private void setColumn(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++, index++){ + for (int z = 0; z < getLength(); z++) { + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { main[index] = combined; @@ -315,9 +305,9 @@ public class HeightMapMCAGenerator implements Extent { public void setBiome(Mask mask, byte biome) { int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -330,10 +320,10 @@ public class HeightMapMCAGenerator implements Extent { private void setOverlay(Mask mask, char combined) { int index = 0; - if (overlay == null) overlay = new char[area]; - for (int z = 0; z < length; z++) { + if (overlay == null) overlay = new char[getArea()]; + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -346,9 +336,9 @@ public class HeightMapMCAGenerator implements Extent { private void setFloor(Mask mask, char combined) { int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -362,9 +352,9 @@ public class HeightMapMCAGenerator implements Extent { private void setMain(Mask mask, char combined) { modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -378,9 +368,9 @@ public class HeightMapMCAGenerator implements Extent { private void setColumn(Mask mask, char combined) { modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -397,12 +387,12 @@ public class HeightMapMCAGenerator implements Extent { setOverlay(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); return; } - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); - if (overlay == null) overlay = new char[area]; + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (overlay == null) overlay = new char[getArea()]; int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { mutable.mutX(x); @@ -418,12 +408,12 @@ public class HeightMapMCAGenerator implements Extent { setMain(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); return; } - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { mutable.mutX(x); @@ -439,11 +429,11 @@ public class HeightMapMCAGenerator implements Extent { setFloor(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); return; } - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { mutable.mutX(x); @@ -459,12 +449,12 @@ public class HeightMapMCAGenerator implements Extent { setColumn(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); return; } - if (img.getWidth() != width || img.getHeight() != length) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); + if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int height = img.getRGB(x, z) & 0xFF; if (height == 255 || height > 0 && white && PseudoRandom.random.nextInt(256) <= height) { mutable.mutX(x); @@ -483,10 +473,10 @@ public class HeightMapMCAGenerator implements Extent { return; } int index = 0; - if (overlay == null) overlay = new char[area]; - for (int z = 0; z < length; z++) { + if (overlay == null) overlay = new char[getArea()]; + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -503,9 +493,9 @@ public class HeightMapMCAGenerator implements Extent { return; } int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -523,9 +513,9 @@ public class HeightMapMCAGenerator implements Extent { } modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -543,9 +533,9 @@ public class HeightMapMCAGenerator implements Extent { } modifiedMain = true; int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++){ + for (int x = 0; x < getWidth(); x++, index++){ int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -577,7 +567,7 @@ public class HeightMapMCAGenerator implements Extent { } private void setOverlay(int value) { - if (overlay == null) overlay = new char[area]; + if (overlay == null) overlay = new char[getArea()]; Arrays.fill(overlay, (char) value); } @@ -587,9 +577,9 @@ public class HeightMapMCAGenerator implements Extent { return; } int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++) { + for (int x = 0; x < getWidth(); x++, index++) { int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -604,9 +594,9 @@ public class HeightMapMCAGenerator implements Extent { return; } int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++) { + for (int x = 0; x < getWidth(); x++, index++) { int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -623,9 +613,9 @@ public class HeightMapMCAGenerator implements Extent { return; } int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++) { + for (int x = 0; x < getWidth(); x++, index++) { int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -635,15 +625,15 @@ public class HeightMapMCAGenerator implements Extent { } public void setOverlay(Pattern value) { - if (overlay == null) overlay = new char[area]; + if (overlay == null) overlay = new char[getArea()]; if (value instanceof BlockPattern) { setOverlay(((BlockPattern) value).getBlock().getCombined()); return; } int index = 0; - for (int z = 0; z < length; z++) { + for (int z = 0; z < getLength(); z++) { mutable.mutZ(z); - for (int x = 0; x < width; x++, index++) { + for (int x = 0; x < getWidth(); x++, index++) { int y = heights[index] & 0xFF; mutable.mutX(x); mutable.mutY(y); @@ -656,321 +646,194 @@ public class HeightMapMCAGenerator implements Extent { Arrays.fill(heights, (byte) value); } - public void generate() throws IOException { - int bcx = 0; - int bcz = 0; - int tcx = (width - 1) >> 4; - int tcz = (length - 1) >> 4; - final ThreadLocal chunkStore = new ThreadLocal() { - @Override - protected MCAChunk initialValue() { - MCAChunk chunk = new MCAChunk(null, 0, 0); - chunk.biomes = new byte[256]; - return chunk; + @Override + public boolean shouldWrite(int chunkX, int chunkZ) { + return true; + } + + @Override + public MCAChunk write(MCAChunk chunk, int csx, int cex, int csz, int cez) { + int cx = chunk.getX(); + int cz = chunk.getZ(); + int[] indexes = indexStore.get(); + for (int i = 0; i < chunk.ids.length; i++) { + byte[] idsArray = chunk.ids[i]; + if (idsArray != null) { + Arrays.fill(idsArray, (byte) 0); + Arrays.fill(chunk.data[i], (byte) 0); } - }; - final ThreadLocal byteStore1 = new ThreadLocal() { - @Override - protected byte[] initialValue() { - return new byte[500000]; + } + int index = 0; + int maxY = 0; + int minY = Integer.MAX_VALUE; + int[] heightMap = chunk.getHeightMapArray(); + int globalIndex; + for (int z = csz; z <= cez; z++) { + globalIndex = z * getWidth() + csx; + for (int x = csx; x <= cex; x++, index++, globalIndex++) { + indexes[index] = globalIndex; + int height = heights[globalIndex] & 0xFF; + heightMap[index] = height; + maxY = Math.max(maxY, height); + minY = Math.min(minY, height); } - }; - final ThreadLocal byteStore2 = new ThreadLocal() { - @Override - protected byte[] initialValue() { - return new byte[500000]; - } - }; - final ThreadLocal deflateStore = new ThreadLocal() { - @Override - protected Deflater initialValue() { - Deflater deflater = new Deflater(1, false); - return deflater; - } - }; - final ThreadLocal indexStore = new ThreadLocal() { - @Override - protected int[] initialValue() { - return new int[256]; - } - }; + } boolean hasOverlay = this.overlay != null; - byte[] fileBuf = new byte[1 << 16]; - for (int mcaZ = 0; mcaZ <= (length >> 9); mcaZ++) { - for (int mcaX = 0; mcaX <= (width >> 9); mcaX++) { - final int fmcaX = mcaX; - final int fmcaZ = mcaZ; - File file = new File(folder, "r." + mcaX + "." + mcaZ + ".mca"); - if (!file.exists()) { - file.createNewFile(); - } - final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw", fileBuf); - final byte[] header = new byte[4096]; - final byte[][] compressed = new byte[1024][]; - int bx = mcaX << 9; - int bz = mcaZ << 9; - int scx = bx >> 4; - int ecx = Math.min(scx + 31, tcx); - int scz = bz >> 4; - int ecz = Math.min(scz + 31, tcz); - short pair = MathMan.pairByte(mcaX, mcaZ); - for (int cz = scz; cz <= ecz; cz++) { - final int csz = cz << 4; - final int cez = Math.min(csz + 15, length - 1); - for (int cx = scx; cx <= ecx; cx++) { - final int csx = cx << 4; - final int cex = Math.min(csx + 15, width - 1); - final int fcx = cx; - final int fcz = cz; - int chunkPair = MathMan.pair((short) cx, (short) cz); - final char[][][] localBlocks = blocks.get(chunkPair); - pool.submit(new Runnable() { - @Override - public void run() { - try { - MCAChunk chunk = chunkStore.get(); - int[] indexes = indexStore.get(); - for (int i = 0; i < chunk.ids.length; i++) { - byte[] idsArray = chunk.ids[i]; - if (idsArray != null) { - Arrays.fill(idsArray, (byte) 0); - } - byte[] dataArray = chunk.data[i]; - if (dataArray != null) { - Arrays.fill(dataArray, (byte) 0); - } - } - int index = 0; - int maxY = 0; - int minY = Integer.MAX_VALUE; - int[] heightMap = chunk.getHeightMapArray(); - int globalIndex; - for (int z = csz; z <= cez; z++) { - globalIndex = z * width + csx; - for (int x = csx; x <= cex; x++, index++, globalIndex++) { - indexes[index] = globalIndex; - int height = heights[globalIndex] & 0xFF; - heightMap[index] = height; - maxY = Math.max(maxY, height); - minY = Math.min(minY, height); - } - } - if (hasOverlay) { - maxY++; - } - int maxLayer = maxY >> 4; - int fillLayers = Math.max(0, (minY - 1)) >> 4; - for (int layer = 0; layer <= maxLayer; layer++) { - if (chunk.ids[layer] == null) { - chunk.ids[layer] = new byte[4096]; - chunk.data[layer] = new byte[2048]; - chunk.skyLight[layer] = new byte[2048]; - chunk.blockLight[layer] = new byte[2048]; - } - } - if (modifiedMain) { // If the main block is modified, we can't short circuit this - for (int layer = 0; layer < fillLayers; layer++) { - index = 0; - byte[] layerIds = chunk.ids[layer]; - byte[] layerDatas = chunk.data[layer]; - for (int z = csz; z <= cez; z++) { - for (int x = csx; x <= cex; x++, index++) { - globalIndex = indexes[index]; - char mainCombined = main[globalIndex]; - byte id = (byte) FaweCache.getId(mainCombined); - int data = FaweCache.getData(mainCombined); - if (data != 0) { - for (int y = 0; y < 16; y++) { - int mainIndex = index + (y << 8); - chunk.setNibble(mainIndex, layerDatas, data); - } - } - for (int y = 0; y < 16; y++) { - layerIds[index + (y << 8)] = id; - } - } - } - } - } else { - for (int layer = 0; layer < fillLayers; layer++) { - Arrays.fill(chunk.ids[layer], (byte) 1); - } - } - for (int layer = fillLayers; layer <= maxLayer; layer++) { - Arrays.fill(chunk.skyLight[layer], (byte) 255); - byte[] layerIds = chunk.ids[layer]; - byte[] layerDatas = chunk.data[layer]; - index = 0; - int startY = layer << 4; - int endY = startY + 15; - for (int z = csz; z <= cez; z++) { - for (int x = csx; x <= cex; x++, index++) { - globalIndex = indexes[index]; - int height = heightMap[index]; - int diff; - if (height > endY) { - diff = 16; - } else if (height >= startY) { - diff = height - startY; - char floorCombined = floor[globalIndex]; - int id = FaweCache.getId(floorCombined); - int floorIndex = index + ((height & 15) << 8); - layerIds[floorIndex] = (byte) id; - int data = FaweCache.getData(floorCombined); - if (data != 0) { - chunk.setNibble(floorIndex, layerDatas, data); - } - if (hasOverlay && height >= startY - 1 && height < endY) { - char overlayCombined = overlay[globalIndex]; - id = FaweCache.getId(overlayCombined); - int overlayIndex = index + (((height + 1) & 15) << 8); - layerIds[overlayIndex] = (byte) id; - data = FaweCache.getData(overlayCombined); - if (data != 0) { - chunk.setNibble(overlayIndex, layerDatas, data); - } - } - } else if (hasOverlay && height == startY - 1) { - char overlayCombined = overlay[globalIndex]; - int id = FaweCache.getId(overlayCombined); - int overlayIndex = index + (((height + 1) & 15) << 8); - layerIds[overlayIndex] = (byte) id; - int data = FaweCache.getData(overlayCombined); - if (data != 0) { - chunk.setNibble(overlayIndex, layerDatas, data); - } - continue; - } else { - continue; - } - char mainCombined = main[globalIndex]; - byte id = (byte) FaweCache.getId(mainCombined); - int data = FaweCache.getData(mainCombined); - if (data != 0) { - for (int y = 0; y < diff; y++) { - int mainIndex = index + (y << 8); - chunk.setNibble(mainIndex, layerDatas, data); - } - } - for (int y = 0; y < diff; y++) { - layerIds[index + (y << 8)] = id; - } - } - } - } - int maxYMod = 15 + (maxLayer << 4); - for (int layer = (maxY >> 4) + 1; layer < 16; layer++) { - chunk.ids[layer] = null; - chunk.data[layer] = null; - } - index = 0; - { // Bedrock - byte[] layerIds = chunk.ids[0]; - for (int z = csz; z <= cez; z++) { - for (int x = csx; x <= cex; x++) { - layerIds[index++] = (byte) 7; - } - } - } - if (localBlocks != null) { - for (int layer = 0; layer < 16; layer++) { - int by = layer << 4; - int ty = by + 15; - index = 0; - for (int y = by; y <= ty; y++, index += 256) { - char[][] yBlocks = localBlocks[y]; - if (yBlocks != null) { - if (chunk.ids[layer] == null) { - chunk.ids[layer] = new byte[4096]; - chunk.data[layer] = new byte[2048]; - chunk.skyLight[layer] = new byte[2048]; - chunk.blockLight[layer] = new byte[2048]; - } - byte[] idsLayer = chunk.ids[layer]; - byte[] dataLayer = chunk.data[layer]; - for (int z = 0; z < yBlocks.length; z++) { - char[] zBlocks = yBlocks[z]; - if (zBlocks != null) { - int zIndex = index + (z << 4); - for (int x = 0; x < zBlocks.length; x++, zIndex++) { - char combined = zBlocks[x]; - if (combined == 0) continue; - int id = FaweCache.getId(combined); - if (!FaweCache.hasData(id)) { - chunk.setIdUnsafe(idsLayer, zIndex, (byte) id); - } else { - chunk.setBlockUnsafe(idsLayer, dataLayer, zIndex, (byte) id, FaweCache.getData(combined)); - } - } - } - } - } - } - } - } - chunk.setLoc(null, fcx, fcz); - byte[] bytes = chunk.toBytes(byteStore1.get()); - byte[] compressedBytes = MainUtil.compress(bytes, byteStore2.get(), deflateStore.get()); - int blocks = (compressed.length + 4095) >> 12; - compressed[((fcx & 31)) + ((fcz & 31) << 5)] = compressedBytes.clone(); - } catch (Throwable e) { - e.printStackTrace(); - } + if (hasOverlay) { + maxY++; + } + int maxLayer = maxY >> 4; + int fillLayers = Math.max(0, (minY - 1)) >> 4; + for (int layer = 0; layer <= maxLayer; layer++) { + if (chunk.ids[layer] == null) { + chunk.ids[layer] = new byte[4096]; + chunk.data[layer] = new byte[2048]; + chunk.skyLight[layer] = new byte[2048]; + chunk.blockLight[layer] = new byte[2048]; + } + } + if (modifiedMain) { // If the main block is modified, we can't short circuit this + for (int layer = 0; layer < fillLayers; layer++) { + index = 0; + byte[] layerIds = chunk.ids[layer]; + byte[] layerDatas = chunk.data[layer]; + for (int z = csz; z <= cez; z++) { + for (int x = csx; x <= cex; x++, index++) { + globalIndex = indexes[index]; + char mainCombined = main[globalIndex]; + byte id = (byte) FaweCache.getId(mainCombined); + int data = FaweCache.getData(mainCombined); + if (data != 0) { + for (int y = 0; y < 16; y++) { + int mainIndex = index + (y << 8); + chunk.setNibble(mainIndex, layerDatas, data); } - }); + } + for (int y = 0; y < 16; y++) { + layerIds[index + (y << 8)] = id; + } } } - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - pool.submit(new Runnable() { - @Override - public void run() { - try { - int totalLength = 8192; - for (int i = 0; i < compressed.length; i++) { - byte[] compressedBytes = compressed[i]; - if (compressedBytes != null) { - int blocks = ((4095 + compressedBytes.length + 5) / 4096) * 4096; - totalLength += blocks; - } + } + } else { + for (int layer = 0; layer < fillLayers; layer++) { + Arrays.fill(chunk.ids[layer], (byte) 1); + } + } + for (int layer = fillLayers; layer <= maxLayer; layer++) { + Arrays.fill(chunk.skyLight[layer], (byte) 255); + byte[] layerIds = chunk.ids[layer]; + byte[] layerDatas = chunk.data[layer]; + index = 0; + int startY = layer << 4; + int endY = startY + 15; + for (int z = csz; z <= cez; z++) { + for (int x = csx; x <= cex; x++, index++) { + globalIndex = indexes[index]; + int height = heightMap[index]; + int diff; + if (height > endY) { + diff = 16; + } else if (height >= startY) { + diff = height - startY; + char floorCombined = floor[globalIndex]; + int id = FaweCache.getId(floorCombined); + int floorIndex = index + ((height & 15) << 8); + layerIds[floorIndex] = (byte) id; + int data = FaweCache.getData(floorCombined); + if (data != 0) { + chunk.setNibble(floorIndex, layerDatas, data); + } + if (hasOverlay && height >= startY - 1 && height < endY) { + char overlayCombined = overlay[globalIndex]; + id = FaweCache.getId(overlayCombined); + int overlayIndex = index + (((height + 1) & 15) << 8); + layerIds[overlayIndex] = (byte) id; + data = FaweCache.getData(overlayCombined); + if (data != 0) { + chunk.setNibble(overlayIndex, layerDatas, data); } - raf.setLength(totalLength); - int offset = 8192; - for (int i = 0; i < compressed.length; i++) { - byte[] compressedBytes = compressed[i]; - if (compressedBytes != null) { - // Set header - int index = i << 2; - int offsetMedium = offset >> 12; - int blocks = ((4095 + compressedBytes.length + 5) / 4096); - header[index] = (byte) (offsetMedium >> 16); - header[index + 1] = (byte) ((offsetMedium >> 8)); - header[index + 2] = (byte) ((offsetMedium >> 0)); - header[index + 3] = (byte) (blocks); - // Write bytes - int cx = (fmcaX << 5) + (i & 31); - int cz = (fmcaZ << 5) + (i >> 5); - raf.seek(offset); - raf.writeInt(compressedBytes.length); - raf.write(2); - raf.write(compressedBytes); - offset += blocks * 4096; + } + } else if (hasOverlay && height == startY - 1) { + char overlayCombined = overlay[globalIndex]; + int id = FaweCache.getId(overlayCombined); + int overlayIndex = index + (((height + 1) & 15) << 8); + layerIds[overlayIndex] = (byte) id; + int data = FaweCache.getData(overlayCombined); + if (data != 0) { + chunk.setNibble(overlayIndex, layerDatas, data); + } + continue; + } else { + continue; + } + char mainCombined = main[globalIndex]; + byte id = (byte) FaweCache.getId(mainCombined); + int data = FaweCache.getData(mainCombined); + if (data != 0) { + for (int y = 0; y < diff; y++) { + int mainIndex = index + (y << 8); + chunk.setNibble(mainIndex, layerDatas, data); + } + } + for (int y = 0; y < diff; y++) { + layerIds[index + (y << 8)] = id; + } + } + } + } + int maxYMod = 15 + (maxLayer << 4); + for (int layer = (maxY >> 4) + 1; layer < 16; layer++) { + chunk.ids[layer] = null; + chunk.data[layer] = null; + } + index = 0; + { // Bedrock + byte[] layerIds = chunk.ids[0]; + for (int z = csz; z <= cez; z++) { + for (int x = csx; x <= cex; x++) { + layerIds[index++] = (byte) 7; + } + } + } + int chunkPair = MathMan.pair((short) cx, (short) cz); + char[][][] localBlocks = blocks.get(chunkPair); + if (localBlocks != null) { + for (int layer = 0; layer < 16; layer++) { + int by = layer << 4; + int ty = by + 15; + index = 0; + for (int y = by; y <= ty; y++, index += 256) { + char[][] yBlocks = localBlocks[y]; + if (yBlocks != null) { + if (chunk.ids[layer] == null) { + chunk.ids[layer] = new byte[4096]; + chunk.data[layer] = new byte[2048]; + chunk.skyLight[layer] = new byte[2048]; + chunk.blockLight[layer] = new byte[2048]; + } + byte[] idsLayer = chunk.ids[layer]; + byte[] dataLayer = chunk.data[layer]; + for (int z = 0; z < yBlocks.length; z++) { + char[] zBlocks = yBlocks[z]; + if (zBlocks != null) { + int zIndex = index + (z << 4); + for (int x = 0; x < zBlocks.length; x++, zIndex++) { + char combined = zBlocks[x]; + if (combined == 0) continue; + int id = FaweCache.getId(combined); + if (!FaweCache.hasData(id)) { + chunk.setIdUnsafe(idsLayer, zIndex, (byte) id); + } else { + chunk.setBlockUnsafe(idsLayer, dataLayer, zIndex, (byte) id, FaweCache.getData(combined)); + } } } - raf.seek(0); - raf.write(header); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - raf.close(); - } catch (IOException e) { - e.printStackTrace(); - } } } - }); + } } } - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + return chunk; } } diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java new file mode 100644 index 00000000..8570375d --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java @@ -0,0 +1,183 @@ +package com.boydti.fawe.jnbt.anvil; + +import com.boydti.fawe.object.io.BufferedRandomAccessFile; +import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.TimeUnit; +import java.util.zip.Deflater; + +public abstract class MCAWriter { + private final File folder; + private final int length; + private final int width; + private final int area; + + public MCAWriter(int width, int length, File regionFolder) { + if (!regionFolder.exists()) { + regionFolder.mkdirs(); + } + this.folder = regionFolder; + this.width = width; + this.length = length; + this.area = width * length; + } + + public final File getFolder() { + return folder; + } + + public final int getWidth() { + return width; + } + + public final int getLength() { + return length; + } + + public final int getArea() { + return area; + } + + public abstract boolean shouldWrite(int chunkX, int chunkZ); + + public abstract MCAChunk write(MCAChunk input, int startX, int endX, int startZ, int endZ); + + public void generate() throws IOException { + final ForkJoinPool pool = new ForkJoinPool(); + int bcx = 0; + int bcz = 0; + int tcx = (width - 1) >> 4; + int tcz = (length - 1) >> 4; + final ThreadLocal chunkStore = new ThreadLocal() { + @Override + protected MCAChunk initialValue() { + MCAChunk chunk = new MCAChunk(null, 0, 0); + chunk.biomes = new byte[256]; + return chunk; + } + }; + final ThreadLocal byteStore1 = new ThreadLocal() { + @Override + protected byte[] initialValue() { + return new byte[500000]; + } + }; + final ThreadLocal byteStore2 = new ThreadLocal() { + @Override + protected byte[] initialValue() { + return new byte[500000]; + } + }; + final ThreadLocal deflateStore = new ThreadLocal() { + @Override + protected Deflater initialValue() { + Deflater deflater = new Deflater(Deflater.BEST_SPEED, false); + return deflater; + } + }; + byte[] fileBuf = new byte[1 << 16]; + for (int mcaZ = 0; mcaZ <= (length >> 9); mcaZ++) { + for (int mcaX = 0; mcaX <= (width >> 9); mcaX++) { + final int fmcaX = mcaX; + final int fmcaZ = mcaZ; + File file = new File(folder, "r." + mcaX + "." + mcaZ + ".mca"); + if (!file.exists()) { + file.createNewFile(); + } + final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw", fileBuf); + final byte[] header = new byte[4096]; + final byte[][] compressed = new byte[1024][]; + int bx = mcaX << 9; + int bz = mcaZ << 9; + int scx = bx >> 4; + int ecx = Math.min(scx + 31, tcx); + int scz = bz >> 4; + int ecz = Math.min(scz + 31, tcz); + short pair = MathMan.pairByte(mcaX, mcaZ); + for (int cz = scz; cz <= ecz; cz++) { + final int csz = cz << 4; + final int cez = Math.min(csz + 15, length - 1); + for (int cx = scx; cx <= ecx; cx++) { + final int csx = cx << 4; + final int cex = Math.min(csx + 15, width - 1); + final int fcx = cx; + final int fcz = cz; + if (shouldWrite(cx, cz)) { + pool.submit(new Runnable() { + @Override + public void run() { + try { + MCAChunk chunk = chunkStore.get(); + chunk.setLoc(null, fcx, fcz); + chunk = write(chunk, csx, cex, csz, cez); + if (chunk != null) { + byte[] bytes = chunk.toBytes(byteStore1.get()); + byte[] compressedBytes = MainUtil.compress(bytes, byteStore2.get(), deflateStore.get()); + int blocks = (compressed.length + 4095) >> 12; + compressed[((fcx & 31)) + ((fcz & 31) << 5)] = compressedBytes.clone(); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + } + } + } + pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + pool.submit(new Runnable() { + @Override + public void run() { + try { + int totalLength = 8192; + for (int i = 0; i < compressed.length; i++) { + byte[] compressedBytes = compressed[i]; + if (compressedBytes != null) { + int blocks = ((4095 + compressedBytes.length + 5) / 4096) * 4096; + totalLength += blocks; + } + } + raf.setLength(totalLength); + int offset = 8192; + for (int i = 0; i < compressed.length; i++) { + byte[] compressedBytes = compressed[i]; + if (compressedBytes != null) { + // Set header + int index = i << 2; + int offsetMedium = offset >> 12; + int blocks = ((4095 + compressedBytes.length + 5) / 4096); + header[index] = (byte) (offsetMedium >> 16); + header[index + 1] = (byte) ((offsetMedium >> 8)); + header[index + 2] = (byte) ((offsetMedium >> 0)); + header[index + 3] = (byte) (blocks); + // Write bytes + int cx = (fmcaX << 5) + (i & 31); + int cz = (fmcaZ << 5) + (i >> 5); + raf.seek(offset); + raf.writeInt(compressedBytes.length); + raf.write(2); + raf.write(compressedBytes); + offset += blocks * 4096; + } + } + raf.seek(0); + raf.write(header); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + raf.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }); + } + } + pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java index 1e323682..0979a3ca 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java @@ -2,7 +2,6 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.PseudoRandom; -import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard; import com.boydti.fawe.object.clipboard.FaweClipboard; import com.boydti.fawe.object.clipboard.OffsetFaweClipboard; @@ -61,10 +60,10 @@ public class ErodeBrush implements Brush { } FaweClipboard finalBuffer = swap % 2 == 0 ? buffer1 : buffer2; - finalBuffer.forEach(new RunnableVal2() { + finalBuffer.forEach(new FaweClipboard.BlockReader() { @Override - public void run(Vector pos, BaseBlock block) { - es.setBlock(pos.getBlockX() + bx, pos.getBlockY() + by, pos.getBlockZ() + bz, block); + public void run(int x, int y, int z, BaseBlock block) { + es.setBlock(x + bx, y + by, z + bz, block); } }, true); } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java index ced7a649..0a75693b 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.clipboard; import com.boydti.fawe.jnbt.NBTStreamer; -import com.boydti.fawe.object.RunnableVal2; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; @@ -78,7 +77,7 @@ public class AbstractDelegateFaweClipboard extends FaweClipboard { } @Override - public void forEach(RunnableVal2 task, boolean air) { + public void forEach(BlockReader task, boolean air) { parent.forEach(task, air); } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java index 5bb4d635..7d34bf07 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java @@ -3,7 +3,6 @@ package com.boydti.fawe.object.clipboard; import com.boydti.fawe.FaweCache; import com.boydti.fawe.jnbt.NBTStreamer; import com.boydti.fawe.object.IntegerTrio; -import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; @@ -156,19 +155,15 @@ public class CPUOptimizedClipboard extends FaweClipboard { } @Override - public void forEach(final RunnableVal2 task, boolean air) { - task.value1 = new Vector(0, 0, 0); + public void forEach(final BlockReader task, boolean air) { for (int y = 0, index = 0; y < height; y++) { for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++, index++) { - task.value2 = getBlock(index); - if (!air && task.value2.getId() == 0) { + BaseBlock block = getBlock(index); + if (!air && block.getId() == 0) { continue; } - task.value1.mutX(x); - task.value1.mutY(y); - task.value1.mutZ(z); - task.run(); + task.run(x, y, z, block); } } } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java index 91bb3337..14ea8537 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java @@ -5,14 +5,12 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.jnbt.NBTStreamer; import com.boydti.fawe.object.IntegerTrio; -import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; @@ -233,6 +231,33 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable { } } + public static long start; + + public static void main(String[] args) throws Throwable { + BaseBlock block = FaweCache.getBlock(0, 0); + DiskOptimizedClipboard clip = new DiskOptimizedClipboard(443, 256, 443, new File("test")); + start = System.currentTimeMillis(); + clip.forEach(new BlockReader() { + @Override + public void run(int x, int y, int z, BaseBlock value2) { + + } + }, true); + clip.close(); +// BufferedRandomAccessFile raf = new BufferedRandomAccessFile(new File("test"), "rw"); +// int len = 50000000; +// raf.setLength(len * 2); +// long start = System.currentTimeMillis(); +// long total = 0; +// for (int i = 0; i < len; i++) { +// total += raf.readChar(); +// } +// raf.close(); + System.out.println(System.currentTimeMillis() - start + "ms"); +// System.out.println("Total " + total); + System.exit(1); + } + @Override public void streamDatas(NBTStreamer.ByteReader task) { try { @@ -257,29 +282,38 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable { } @Override - public void forEach(final RunnableVal2 task, boolean air) { + public void forEach(final BlockReader task, boolean air) { try { raf.seek(HEADER_SIZE); - BlockVector pos = new BlockVector(0, 0, 0); IntegerTrio trio = new IntegerTrio(); + final boolean hasTile = !nbtMap.isEmpty(); if (air) { - for (int y = 0; y < height; y++) { - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++) { - int combinedId = raf.readChar(); - BaseBlock block = FaweCache.CACHE_BLOCK[combinedId]; - if (FaweCache.hasNBT(block.getId())) { - trio.set(x, y, z); - CompoundTag nbt = nbtMap.get(trio); - if (nbt != null) { - block = new BaseBlock(block.getId(), block.getData()); - block.setNbtData(nbt); + if (hasTile) { + for (int y = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + for (int x = 0; x < width; x++) { + char combinedId = raf.readChar(); + BaseBlock block = FaweCache.CACHE_BLOCK[combinedId]; + if (block.canStoreNBTData()) { + trio.set(x, y, z); + CompoundTag nbt = nbtMap.get(trio); + if (nbt != null) { + block = new BaseBlock(block.getId(), block.getData()); + block.setNbtData(nbt); + } } + task.run(x, y, z, block); + } + } + } + } else { + for (int y = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + for (int x = 0; x < width; x++) { + char combinedId = raf.readChar(); + BaseBlock block = FaweCache.CACHE_BLOCK[combinedId]; + task.run(x, y, z, block); } - pos.mutX(x); - pos.mutY(y); - pos.mutZ(z); - task.run(pos, block); } } } @@ -298,10 +332,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable { block.setNbtData(nbt); } } - pos.mutX(x); - pos.mutY(y); - pos.mutZ(z); - task.run(pos, block); + task.run(x, y, z, block); } } } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java index 0096fc1a..df5aafa9 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.clipboard; import com.boydti.fawe.jnbt.NBTStreamer; -import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; @@ -50,23 +49,27 @@ public abstract class FaweClipboard { * @param task * @param air */ - public abstract void forEach(final RunnableVal2 task, boolean air); + public abstract void forEach(BlockReader task, boolean air); + + public static abstract class BlockReader { + public abstract void run(int x, int y, int z, BaseBlock block); + } public void streamIds(final NBTStreamer.ByteReader task) { - forEach(new RunnableVal2() { + forEach(new BlockReader() { private int index = 0; @Override - public void run(Vector pos, BaseBlock block) { + public void run(int x, int y, int z, BaseBlock block) { task.run(index++, block.getId()); } }, true); } public void streamDatas(final NBTStreamer.ByteReader task) { - forEach(new RunnableVal2() { + forEach(new BlockReader() { private int index = 0; @Override - public void run(Vector pos, BaseBlock block) { + public void run(int x, int y, int z, BaseBlock block) { task.run(index++, block.getData()); } }, true); @@ -74,16 +77,16 @@ public abstract class FaweClipboard { public List getTileEntities() { final List tiles = new ArrayList<>(); - forEach(new RunnableVal2() { + forEach(new BlockReader() { private int index = 0; @Override - public void run(Vector pos, BaseBlock block) { + public void run(int x, int y, int z, BaseBlock block) { CompoundTag tag = block.getNbtData(); if (tag != null) { Map values = ReflectionUtils.getMap(tag.getValue()); - values.put("x", new IntTag(pos.getBlockX())); - values.put("y", new IntTag(pos.getBlockY())); - values.put("z", new IntTag(pos.getBlockZ())); + values.put("x", new IntTag(x)); + values.put("y", new IntTag(y)); + values.put("z", new IntTag(z)); tiles.add(tag); } } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java index b5ad365a..43f148a2 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java @@ -4,7 +4,6 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.jnbt.NBTStreamer; import com.boydti.fawe.object.IntegerTrio; -import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.CompoundTag; @@ -377,20 +376,26 @@ public class MemoryOptimizedClipboard extends FaweClipboard { } @Override - public void forEach(final RunnableVal2 task, boolean air) { + public void forEach(final BlockReader task, final boolean air) { // Fawe.debug("Compressed: " + size() + "b | Uncompressed: " + (volume << 0x5) + "b"); - task.value1 = new Vector(0, 0, 0); - for (int y = 0, index = 0; y < height; y++) { - for (int z = 0; z < length; z++) { - for (int x = 0; x < width; x++, index++) { - task.value2 = getBlock(index); - if (!air && task.value2.getId() == 0) { - continue; + if (air) { + for (int y = 0, index = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + for (int x = 0; x < width; x++, index++) { + BaseBlock block = getBlock(index); + task.run(x, y, z, block); + } + } + } + } else { + for (int y = 0, index = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + for (int x = 0; x < width; x++, index++) { + BaseBlock block = getBlock(index); + if (block.getId() == 0) { + task.run(x, y, z, block); + } } - task.value1.mutX(x); - task.value1.mutY(y); - task.value1.mutZ(z); - task.run(); } } } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java index 37f27523..3ccc5238 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java @@ -1,8 +1,6 @@ package com.boydti.fawe.object.clipboard; -import com.boydti.fawe.object.RunnableVal2; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; public class OffsetFaweClipboard extends AbstractDelegateFaweClipboard { @@ -35,14 +33,11 @@ public class OffsetFaweClipboard extends AbstractDelegateFaweClipboard { } @Override - public void forEach(final RunnableVal2 task, boolean air) { - super.forEach(new RunnableVal2() { + public void forEach(final BlockReader task, boolean air) { + super.forEach(new BlockReader() { @Override - public void run(Vector value, BaseBlock block) { - value.mutX(value.getX() - ox); - value.mutY(value.getY() - oy); - value.mutZ(value.getZ() - oz); - task.run(value, block); + public void run(int x, int y, int z, BaseBlock block) { + task.run(x - ox, y - oy, z - oz, block); } }, air); } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java index 815066c6..e1049241 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java @@ -1,6 +1,5 @@ package com.boydti.fawe.object.clipboard; -import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; @@ -47,7 +46,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { } @Override - public void forEach(final RunnableVal2 task, boolean air) { + public void forEach(BlockReader task, boolean air) { Vector min = region.getMinimumPoint(); Vector max = region.getMaximumPoint(); final Vector pos = new Vector(); @@ -57,21 +56,18 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() { @Override public boolean apply(Vector pos) throws WorldEditException { - int x = pos.getBlockX(); - int y = pos.getBlockY(); - int z = pos.getBlockZ(); - BaseBlock block = getBlockAbs(x, y, z); - pos.mutX(x - mx); - pos.mutY(y - my); - pos.mutZ(z - mz); + BaseBlock block = getBlockAbs(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); + int x = pos.getBlockX() - mx; + int y = pos.getBlockY() - my; + int z = pos.getBlockZ() - mz; CompoundTag tag = block.getNbtData(); if (tag != null) { Map values = ReflectionUtils.getMap(tag.getValue()); - values.put("x", new IntTag(pos.getBlockX())); - values.put("y", new IntTag(pos.getBlockY())); - values.put("z", new IntTag(pos.getBlockZ())); + values.put("x", new IntTag(x)); + values.put("y", new IntTag(y)); + values.put("z", new IntTag(z)); } - task.run(pos, block); + task.run(x, y, z, block); return true; } }, editSession); @@ -82,27 +78,21 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { RegionVisitor visitor = new RegionVisitor(cuboidEquivalent, new RegionFunction() { @Override public boolean apply(Vector pos) throws WorldEditException { + int x = pos.getBlockX() - mx; + int y = pos.getBlockY() - my; + int z = pos.getBlockZ() - mz; if (region.contains(pos)) { - int x = pos.getBlockX(); - int y = pos.getBlockY(); - int z = pos.getBlockZ(); - BaseBlock block = getBlockAbs(x, y, z); - pos.mutX(x - mx); - pos.mutY(y - my); - pos.mutZ(z - mz); + BaseBlock block = getBlockAbs(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); CompoundTag tag = block.getNbtData(); if (tag != null) { Map values = ReflectionUtils.getMap(tag.getValue()); - values.put("x", new IntTag(pos.getBlockX())); - values.put("y", new IntTag(pos.getBlockY())); - values.put("z", new IntTag(pos.getBlockZ())); + values.put("x", new IntTag(x)); + values.put("y", new IntTag(y)); + values.put("z", new IntTag(z)); } - task.run(pos, block); + task.run(x, y, z, block); } else { - pos.mutX(pos.getBlockX() - mx); - pos.mutY(pos.getBlockY() - my); - pos.mutZ(pos.getBlockZ() - mz); - task.run(pos, EditSession.nullBlock); + task.run(x, y, z, EditSession.nullBlock); } return true; } @@ -111,32 +101,29 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { } } else { for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { + pos.mutY(y); + int yy = pos.getBlockY() - my; for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { + pos.mutZ(z); + int zz = pos.getBlockZ() - mz; for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { pos.mutX(x); - pos.mutY(y); - pos.mutZ(z); + int xx = pos.getBlockX() - mx; if (region.contains(pos)) { BaseBlock block = getBlockAbs(x, y, z); if (!air && block == EditSession.nullBlock) { continue; } - pos.mutX(pos.getX() - mx); - pos.mutY(pos.getY() - my); - pos.mutZ(pos.getZ() - mz); CompoundTag tag = block.getNbtData(); if (tag != null) { Map values = ReflectionUtils.getMap(tag.getValue()); - values.put("x", new IntTag(pos.getBlockX())); - values.put("y", new IntTag(pos.getBlockY())); - values.put("z", new IntTag(pos.getBlockZ())); + values.put("x", new IntTag(xx)); + values.put("y", new IntTag(yy)); + values.put("z", new IntTag(zz)); } - task.run(pos, block); + task.run(xx, yy, zz, block); } else if (air) { - pos.mutX(pos.getX() - mx); - pos.mutY(pos.getY() - my); - pos.mutZ(pos.getZ() - mz); - task.run(pos, EditSession.nullBlock); + task.run(xx, yy, zz, EditSession.nullBlock); } } } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java index 1992c256..0c0bb351 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCutClipboard.java @@ -28,7 +28,7 @@ public class WorldCutClipboard extends WorldCopyClipboard { } @Override - public void forEach(RunnableVal2 task, boolean air) { + public void forEach(BlockReader task, boolean air) { super.forEach(task, air); editSession.flushQueue(); } diff --git a/core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java b/core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java index 2f20424f..1a5e43f5 100644 --- a/core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java +++ b/core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java @@ -1,7 +1,7 @@ package com.boydti.fawe.object.schematic; import com.boydti.fawe.object.HasFaweQueue; -import com.boydti.fawe.object.RunnableVal2; +import com.boydti.fawe.object.clipboard.FaweClipboard; import com.boydti.fawe.object.clipboard.ReadOnlyClipboard; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.MaskTraverser; @@ -167,18 +167,13 @@ public class Schematic { final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY(); final int relz = to.getBlockZ() + bot.getBlockZ() - origin.getBlockZ(); BlockArrayClipboard bac = (BlockArrayClipboard) clipboard; - bac.IMP.forEach(new RunnableVal2() { + bac.IMP.forEach(new FaweClipboard.BlockReader() { @Override - public void run(Vector mutable, BaseBlock block) { - mutable.mutX(mutable.getX() + relx); - mutable.mutY(mutable.getY() + rely); - mutable.mutZ(mutable.getZ() + relz); - if (mutable.getY() >= 0 && mutable.getY() <= maxY) { - try { - extent.setBlock(mutable, block); - } catch (WorldEditException e) { - throw new RuntimeException(e); - } + public void run(int x, int y, int z, BaseBlock block) { + try { + extent.setBlock(x + relx, y + rely, z + relz, block); + } catch (WorldEditException e) { + throw new RuntimeException(e); } } }, pasteAir); @@ -194,12 +189,7 @@ public class Schematic { if (block == EditSession.nullBlock && !pasteAir) { return false; } - mutable.mutX(mutable.getX() + relx); - mutable.mutY(mutable.getY() + rely); - mutable.mutZ(mutable.getZ() + relz); - if (mutable.getY() >= 0 && mutable.getY() <= maxY) { - return extent.setBlock(mutable, block); - } + extent.setBlock(mutable.getBlockX() + relx, mutable.getBlockY() + rely, mutable.getBlockZ() + relz, block); return false; } }, (HasFaweQueue) (extent instanceof HasFaweQueue ? extent : null)); diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index 312a42f0..4a5c5983 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -250,7 +250,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting if (combineStages == null) { combineStages = Settings.IMP.HISTORY.COMBINE_STAGES && !(queue instanceof MCAQueue); } - if (limit.FAST_PLACEMENT) { + if (!limit.FAST_PLACEMENT) { combineStages = false; } if (checkMemory) { @@ -314,6 +314,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting if (this.blockBag != null && limit.INVENTORY_MODE > 0) { changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1); } + System.out.println("Combine stages " + combineStages); if (combineStages) { changeTask = changeSet; changeSet.addChangeTask(queue); @@ -3213,17 +3214,13 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } @Override - public boolean clearContainerBlockContents(Vector position) { - BaseBlock block = getBlock(position); + public boolean clearContainerBlockContents(Vector pos) { + BaseBlock block = getBlock(pos); CompoundTag nbt = block.getNbtData(); if (nbt != null) { if (nbt.containsKey("items")) { block.setNbtData(null); - try { - return setBlock(position, block); - } catch (WorldEditException e) { - e.printStackTrace(); - } + return setBlock(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), block); } } return false; diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java index 6f556428..d93fb3e6 100644 --- a/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java +++ b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java @@ -237,6 +237,11 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern { return getNbtData() != null; } + public boolean canStoreNBTData() { + return FaweCache.hasNBT(getId()); + } + + @Override public String getNbtId() { CompoundTag nbtData = getNbtData(); diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableBlock.java index ef7fee33..ba7206ca 100644 --- a/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableBlock.java +++ b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableBlock.java @@ -29,6 +29,11 @@ public class ImmutableBlock extends BaseBlock { return clone.flip(direction); } + @Override + public boolean canStoreNBTData() { + return false; + } + @Override public boolean isImmutable() { return true; diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableDatalessBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableDatalessBlock.java index da580444..74e02f76 100644 --- a/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableDatalessBlock.java +++ b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableDatalessBlock.java @@ -23,4 +23,9 @@ public class ImmutableDatalessBlock extends ImmutableBlock { return false; } } + + @Override + public boolean canStoreNBTData() { + return false; + } } diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableNBTBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableNBTBlock.java new file mode 100644 index 00000000..83060eb3 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableNBTBlock.java @@ -0,0 +1,12 @@ +package com.sk89q.worldedit.blocks; + +public class ImmutableNBTBlock extends ImmutableBlock { + public ImmutableNBTBlock(int id, int data) { + super(id, data); + } + + @Override + public boolean canStoreNBTData() { + return true; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicWriter.java b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicWriter.java index eae86179..84dd2d31 100644 --- a/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicWriter.java +++ b/core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicWriter.java @@ -2,7 +2,6 @@ package com.sk89q.worldedit.extent.clipboard.io; import com.boydti.fawe.FaweCache; import com.boydti.fawe.jnbt.NBTStreamer; -import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.clipboard.FaweClipboard; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.ByteArrayTag; @@ -54,7 +53,7 @@ public class SchematicWriter implements ClipboardWriter { this.outputStream = outputStream; } - private static class ForEach extends RunnableVal2 { + private static class ForEach extends FaweClipboard.BlockReader { int x = -1; int y = 0; int z = 0; @@ -76,10 +75,7 @@ public class SchematicWriter implements ClipboardWriter { } @Override - public void run(Vector point, BaseBlock block) { - int x = (int) point.getX(); - int y = (int) point.getY(); - int z = (int) point.getZ(); + public void run(int x, int y, int z, BaseBlock block) { if (this.x == x - 1 && this.y == y && this.z == z) { this.x++; index++; @@ -164,6 +160,7 @@ public class SchematicWriter implements ClipboardWriter { public void run(int index, int byteValue) { try { if (byteValue >= 256) { + System.out.println("Add block"); hasAdd = true; } if (FaweCache.hasData(byteValue)) { @@ -205,6 +202,7 @@ public class SchematicWriter implements ClipboardWriter { @Override public void run(int index, int byteValue) { try { + System.out.println("Add " + (byteValue >> 8)); rawStream.writeByte(byteValue >> 8); } catch (IOException e) { e.printStackTrace(); @@ -312,10 +310,10 @@ public class SchematicWriter implements ClipboardWriter { MutableBlockVector mutable = new MutableBlockVector(0, 0, 0); ForEach forEach = new ForEach(yarea, zwidth, blocks, blockData, tileEntities); for (Vector point : region) { - mutable.mutX((point.getX() - mx)); - mutable.mutY((point.getY() - my)); - mutable.mutZ((point.getZ() - mz)); - forEach.run(mutable, clipboard.getBlock(point)); + int x = (point.getBlockX() - mx); + int y = (point.getBlockY() - my); + int z = (point.getBlockZ() - mz); + forEach.run(x, y, z, clipboard.getBlock(point)); } addBlocks = forEach.addBlocks; }