From d09dbee3c7c2239d623aa92982e621582efe947e Mon Sep 17 00:00:00 2001 From: boy0001 Date: Thu, 23 Jul 2015 02:33:22 +1000 Subject: [PATCH] Optimizations to schematic loading / pasting -> ~10,000,000 bps The downside is it completely ignores entities and such, so WorldEdit is the way to go if you need precision but don't care for large sizes or speed. --- .../plot/commands/Claim.java | 13 +- .../plot/commands/SchematicCmd.java | 78 +---- .../plot/config/Settings.java | 2 +- .../plot/generator/HybridPlotManager.java | 4 +- .../plot/generator/HybridPlotWorld.java | 24 +- .../plot/generator/SquarePlotManager.java | 2 +- .../plot/listeners/PlayerEvents.java | 6 +- .../plot/object/Plot.java | 16 +- .../plot/util/SchematicHandler.java | 325 +++++++++++++----- 9 files changed, 296 insertions(+), 174 deletions(-) diff --git a/src/main/java/com/intellectualcrafters/plot/commands/Claim.java b/src/main/java/com/intellectualcrafters/plot/commands/Claim.java index a59d6f10d..1d618e537 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/Claim.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/Claim.java @@ -27,6 +27,7 @@ import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotWorld; +import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.util.EconHandler; import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.MainUtil; @@ -72,7 +73,17 @@ public class Claim extends SubCommand { sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE); } } - SchematicHandler.manager.paste(sch, plot2, 0, 0); + SchematicHandler.manager.paste(sch, plot2, 0, 0, new RunnableVal() { + @Override + public void run() { + if (value) { + MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_SUCCESS); + } + else { + MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_FAILED); + } + } + }); } PS.get().getPlotManager(world).claimPlot(plotworld, plot); } diff --git a/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java b/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java index c9f55f82d..6a11db9c9 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java @@ -30,6 +30,7 @@ import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.util.BlockManager; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.Permissions; @@ -89,69 +90,24 @@ public class SchematicCmd extends SubCommand { TaskManager.runTaskAsync(new Runnable() { @Override public void run() { - try { - final Schematic schematic = SchematicHandler.manager.getSchematic(file2); - if (schematic == null) { - sendMessage(plr, C.SCHEMATIC_INVALID, "non-existent or not in gzip format"); - SchematicCmd.this.running = false; - return; - } - final int x; - final int z; - final Plot plot2 = MainUtil.getPlot(loc); - final Dimension dem = schematic.getSchematicDimension(); - final Location bot = MainUtil.getPlotBottomLoc(loc.getWorld(), plot2.id).add(1, 0, 1); - final int length2 = MainUtil.getPlotWidth(loc.getWorld(), plot2.id); - if ((dem.getX() > length2) || (dem.getZ() > length2)) { - sendMessage(plr, C.SCHEMATIC_INVALID, String.format("Wrong size (x: %s, z: %d) vs %d ", dem.getX(), dem.getZ(), length2)); - SchematicCmd.this.running = false; - return; - } - if ((dem.getX() != length2) || (dem.getZ() != length2)) { - final Location loc = plr.getLocation(); - x = Math.min(length2 - dem.getX(), loc.getX() - bot.getX()); - z = Math.min(length2 - dem.getZ(), loc.getZ() - bot.getZ()); - } else { - x = 0; - z = 0; - } - final DataCollection[] b = schematic.getBlockCollection(); - final int sy = BlockManager.manager.getHeighestBlock(bot); - final int WIDTH = schematic.getSchematicDimension().getX(); - final int LENGTH = schematic.getSchematicDimension().getZ(); - final Location l1; - if (!(schematic.getSchematicDimension().getY() == BukkitUtil.getMaxHeight(loc.getWorld()))) { - l1 = bot.add(0, sy - 1, 0); - } - else { - l1 = bot; - } - final int blen = b.length - 1; - SchematicCmd.this.task = TaskManager.runTaskRepeat(new Runnable() { - @Override - public void run() { - boolean result = false; - while (!result) { - final int start = SchematicCmd.this.counter * 5000; - if (start > blen) { - SchematicHandler.manager.pasteStates(schematic, plot, 0, 0); - sendMessage(plr, C.SCHEMATIC_PASTE_SUCCESS); - SchematicCmd.this.running = false; - PS.get().TASK.cancelTask(SchematicCmd.this.task); - return; - } - final int end = Math.min(start + 5000, blen); - result = SchematicHandler.manager.pastePart(loc.getWorld(), b, l1, x, z, start, end, WIDTH, LENGTH); - SchematicCmd.this.counter++; - } - } - }, 1); - } - catch (Exception e) { - e.printStackTrace(); + final Schematic schematic = SchematicHandler.manager.getSchematic(file2); + if (schematic == null) { SchematicCmd.this.running = false; - MainUtil.sendMessage(plr, "&cAn error occured, see console for more information"); + sendMessage(plr, C.SCHEMATIC_INVALID, "non-existent or not in gzip format"); + return; } + SchematicHandler.manager.paste(schematic, plot, 0, 0, new RunnableVal() { + @Override + public void run() { + SchematicCmd.this.running = false; + if (this.value) { + sendMessage(plr, C.SCHEMATIC_PASTE_SUCCESS); + } + else { + sendMessage(plr, C.SCHEMATIC_PASTE_FAILED); + } + } + }); } }); break; diff --git a/src/main/java/com/intellectualcrafters/plot/config/Settings.java b/src/main/java/com/intellectualcrafters/plot/config/Settings.java index 98d33ebc8..75e973845 100644 --- a/src/main/java/com/intellectualcrafters/plot/config/Settings.java +++ b/src/main/java/com/intellectualcrafters/plot/config/Settings.java @@ -162,7 +162,7 @@ public class Settings { * Days until a plot gets cleared */ public static int AUTO_CLEAR_DAYS = 360; - public static int CLEAR_THRESHOLD = -1; + public static int CLEAR_THRESHOLD = 1; public static int CLEAR_INTERVAL = 120; /** * API Location diff --git a/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java b/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java index ea9d71281..ede0562e7 100644 --- a/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java +++ b/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java @@ -83,7 +83,7 @@ public class HybridPlotManager extends ClassicPlotManager { Location bot = getPlotBottomLocAbs(hpw, id2); Location top = getPlotTopLocAbs(hpw, id); Location pos1 = new Location(plot.world, top.getX() + 1, 0, bot.getZ()); - Location pos2 = new Location(plot.world, bot.getX(), 256, top.getZ() + 1); + Location pos2 = new Location(plot.world, bot.getX(), 255, top.getZ() + 1); createSchemAbs(hpw, pos1, pos2, hpw.ROAD_HEIGHT, true); return true; } @@ -139,7 +139,7 @@ public class HybridPlotManager extends ClassicPlotManager { Location bot = getPlotBottomLocAbs(hpw, id2); Location top = getPlotTopLocAbs(hpw, id); Location pos1 = new Location(plot.world, bot.getX(), 0, top.getZ() + 1); - Location pos2 = new Location(plot.world, top.getX() + 1, 256, bot.getZ()); + Location pos2 = new Location(plot.world, top.getX() + 1, 255, bot.getZ()); createSchemAbs(hpw, pos1, pos2, hpw.ROAD_HEIGHT, true); return true; } diff --git a/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java b/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java index 5fec082c4..b9f7cedee 100644 --- a/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java +++ b/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java @@ -89,7 +89,8 @@ public class HybridPlotWorld extends ClassicPlotWorld { } if (schem3 != null) { this.PLOT_SCHEMATIC = true; - final DataCollection[] blocks3 = schem3.getBlockCollection(); + byte[] ids = schem3.getIds(); + byte[] datas = schem3.getDatas(); final Dimension d3 = schem3.getSchematicDimension(); final short w3 = (short) d3.getX(); final short l3 = (short) d3.getZ(); @@ -106,8 +107,8 @@ public class HybridPlotWorld extends ClassicPlotWorld { for (short z = 0; z < l3; z++) { for (short y = 0; y < h3; y++) { final int index = (y * w3 * l3) + (z * w3) + x; - final short id = blocks3[index].getBlock(); - final byte data = blocks3[index].getData(); + final short id = ids[index]; + final byte data = ids[index]; if (id != 0) { addOverlayBlock((short) (x + shift + oddshift + center_shift_x), (y), (short) (z + shift + oddshift + center_shift_z), id, data, false); } @@ -139,8 +140,13 @@ public class HybridPlotWorld extends ClassicPlotWorld { this.ROAD_SCHEMATIC_ENABLED = true; // Do not populate road if using schematic population this.ROAD_BLOCK = new PlotBlock(this.ROAD_BLOCK.id, (byte) 0); - final DataCollection[] blocks1 = schem1.getBlockCollection(); - final DataCollection[] blocks2 = schem2.getBlockCollection(); + + byte[] ids1 = schem1.getIds(); + byte[] datas1 = schem1.getDatas(); + + byte[] ids2 = schem2.getIds(); + byte[] datas2 = schem2.getDatas(); + final Dimension d1 = schem1.getSchematicDimension(); final short w1 = (short) d1.getX(); final short l1 = (short) d1.getZ(); @@ -154,8 +160,8 @@ public class HybridPlotWorld extends ClassicPlotWorld { for (short z = 0; z < l1; z++) { for (short y = 0; y < h1; y++) { final int index = (y * w1 * l1) + (z * w1) + x; - final short id = blocks1[index].getBlock(); - final byte data = blocks1[index].getData(); + final short id = ids1[index]; + final byte data = datas1[index]; if (id != 0) { addOverlayBlock((short) (x - (shift)), (y), (short) (z + shift + oddshift), id, data, false); addOverlayBlock((short) (z + shift + oddshift), (y), (short) (x - shift), id, data, true); @@ -167,8 +173,8 @@ public class HybridPlotWorld extends ClassicPlotWorld { for (short z = 0; z < l2; z++) { for (short y = 0; y < h2; y++) { final int index = (y * w2 * l2) + (z * w2) + x; - final short id = blocks2[index].getBlock(); - final byte data = blocks2[index].getData(); + final short id = ids2[index]; + final byte data = datas2[index]; if (id != 0) { addOverlayBlock((short) (x - shift), (y), (short) (z - shift), id, data, false); } diff --git a/src/main/java/com/intellectualcrafters/plot/generator/SquarePlotManager.java b/src/main/java/com/intellectualcrafters/plot/generator/SquarePlotManager.java index 1c39abd0c..8bf5cb277 100644 --- a/src/main/java/com/intellectualcrafters/plot/generator/SquarePlotManager.java +++ b/src/main/java/com/intellectualcrafters/plot/generator/SquarePlotManager.java @@ -28,7 +28,7 @@ public abstract class SquarePlotManager extends GridPlotManager { final int pz = plotid.y; final int x = dpw.ROAD_OFFSET_X + (px * (dpw.ROAD_WIDTH + dpw.PLOT_WIDTH)) - ((int) Math.floor(dpw.ROAD_WIDTH / 2)) - 1; final int z = dpw.ROAD_OFFSET_Z + (pz * (dpw.ROAD_WIDTH + dpw.PLOT_WIDTH)) - ((int) Math.floor(dpw.ROAD_WIDTH / 2)) - 1; - return new Location(plotworld.worldname, x, 256, z); + return new Location(plotworld.worldname, x, 255, z); } @Override diff --git a/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java b/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java index f8802de3a..1b1e5f77e 100644 --- a/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java +++ b/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java @@ -1950,10 +1950,10 @@ public class PlayerEvents extends com.intellectualcrafters.plot.listeners.PlotLi Block block = event.getBlockPlaced(); sendBlockChange(block.getLocation(), block.getType(), block.getData()); } - int temporary; - if (!player.hasPermission("plots.admin.build.heightlimit") && loc.getY() >= (temporary = PS.get().getPlotWorld(world).MAX_BUILD_HEIGHT)) { + PlotWorld pw = PS.get().getPlotWorld(loc.getWorld()); + if (loc.getY() >= pw.MAX_BUILD_HEIGHT && !Permissions.hasPermission(pp, "plots.admin.build.heightlimit")) { event.setCancelled(true); - MainUtil.sendMessage(pp, C.HEIGHT_LIMIT.s().replace("{limit}", "" + temporary)); + MainUtil.sendMessage(pp, C.HEIGHT_LIMIT.s().replace("{limit}", "" + pw.MAX_BUILD_HEIGHT)); return; } return; diff --git a/src/main/java/com/intellectualcrafters/plot/object/Plot.java b/src/main/java/com/intellectualcrafters/plot/object/Plot.java index 6cc22f14c..226245341 100644 --- a/src/main/java/com/intellectualcrafters/plot/object/Plot.java +++ b/src/main/java/com/intellectualcrafters/plot/object/Plot.java @@ -39,7 +39,7 @@ import com.intellectualcrafters.plot.util.MainUtil; * @author Empire92 */ @SuppressWarnings("javadoc") -public class Plot implements Cloneable { +public class Plot { /** * plot ID */ @@ -251,20 +251,6 @@ public class Plot implements Cloneable { return this.members; } - /** - * Get a clone of the plot - * - * @return Plot - */ - @Override - public Object clone() throws CloneNotSupportedException { - final Plot p = (Plot) super.clone(); - if (!p.equals(this) || (p != this)) { - return new Plot(this.id, this.owner, this.trusted, this.members, this.denied, this.settings.getAlias(), this.settings.getPosition(), this.settings.flags.values(), this.world, this.settings.getMerged()); - } - return p; - } - /** * Deny someone (use DBFunc.addDenied() as well) * diff --git a/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java b/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java index 3c7ece164..7dffacbd9 100644 --- a/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java +++ b/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java @@ -1,20 +1,16 @@ package com.intellectualcrafters.plot.util; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; -import java.io.Reader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -26,8 +22,6 @@ import java.util.UUID; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import org.bukkit.Bukkit; - import com.intellectualcrafters.jnbt.ByteArrayTag; import com.intellectualcrafters.jnbt.CompoundTag; import com.intellectualcrafters.jnbt.IntTag; @@ -41,6 +35,7 @@ import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.config.Settings; import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.schematic.PlotItem; @@ -146,52 +141,167 @@ public abstract class SchematicHandler { * * @return boolean true if succeeded */ - public boolean paste(final Schematic schematic, final Plot plot, final int x_offset, final int z_offset) { - if (schematic == null) { - PS.log("Schematic == null :|"); - return false; - } - try { - final Dimension demensions = schematic.getSchematicDimension(); - final int WIDTH = demensions.getX(); - final int LENGTH = demensions.getZ(); - final int HEIGHT = demensions.getY(); - final DataCollection[] blocks = schematic.getBlockCollection(); - Location l1 = MainUtil.getPlotBottomLoc(plot.world, plot.getId()); - final int sy = BukkitUtil.getHeighestBlock(plot.world, l1.getX() + 1, l1.getZ() + 1); - if (!(HEIGHT == BukkitUtil.getMaxHeight(plot.world))) { - l1 = l1.add(1, sy - 1, 1); - } - else { - l1 = l1.add(1, 0, 1); - } - int X = l1.getX(); - int Y = l1.getY(); - int Z = l1.getZ(); - final int[] xl = new int[blocks.length]; - final int[] yl = new int[blocks.length]; - final int[] zl = new int[blocks.length]; - final int[] ids = new int[blocks.length]; - final byte[] data = new byte[blocks.length]; - for (int x = 0; x < WIDTH; x++) { - for (int z = 0; z < LENGTH; z++) { - for (int y = 0; y < HEIGHT; y++) { - final int index = (y * WIDTH * LENGTH) + (z * WIDTH) + x; - final DataCollection block = blocks[index]; - xl[index] = x + X; - yl[index] = y + Y; - zl[index] = z + Z; - ids[index] = block.block; - data[index] = block.data; + public void paste(final Schematic schematic, final Plot plot, final int x_offset, final int z_offset, final RunnableVal whenDone) { + System.out.print(1); + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + System.out.print(2); + if (whenDone != null) whenDone.value = false; + if (schematic == null) { + PS.log("Schematic == null :|"); + TaskManager.runTask(whenDone); + return; + } + try { + System.out.print(3); + final Dimension demensions = schematic.getSchematicDimension(); + final int WIDTH = demensions.getX(); + final int LENGTH = demensions.getZ(); + final int HEIGHT = demensions.getY(); + + byte[] ids = schematic.ids; + byte[] datas = schematic.datas; + + int y_offset; + if (HEIGHT >= 256) { + y_offset = -1; } + else { + y_offset = BukkitUtil.getMaxHeight(plot.world) - 1; + } + + Location bottom = MainUtil.getPlotBottomLoc(plot.world, plot.id).add(1 + x_offset, y_offset, 1 + z_offset); + + int X = bottom.getX(); + int Y = bottom.getY(); + int Z = bottom.getZ(); + + int id; + + System.out.print(4); + + System.out.print("HEIGHT: " + HEIGHT); + + for (int y = 0; y < Math.max(256, HEIGHT); y++) { + int i1 = y * WIDTH * LENGTH; + for (int z = 0; z < LENGTH; z++) { + int i2 = z * WIDTH + i1; + for (int x = 0; x < WIDTH; x++) { + int i = i2 + x; + id = ids[i]; + switch(id) { + case 0: + case 2: + case 4: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 24: + case 30: + case 32: + case 37: + case 39: + case 40: + case 41: + case 42: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 55: + case 56: + case 57: + case 58: + case 60: + case 7: + case 8: + case 9: + case 10: + case 11: + case 73: + case 74: + case 75: + case 76: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 85: + case 87: + case 88: + case 101: + case 102: + case 103: + case 110: + case 112: + case 113: + case 121: + case 122: + case 129: + case 133: + case 165: + case 166: + case 169: + case 170: + case 172: + case 173: + case 174: + case 181: + case 182: + case 188: + case 189: + case 190: + case 191: + case 192: { + SetBlockQueue.setBlock(plot.world, X + x, Y + y, Z + z, id); + break; + } + default: { + SetBlockQueue.setBlock(plot.world, X + x, Y + y, Z + z, new PlotBlock((short) id, (byte) datas[i])); + break; + } + } + // set block + } + } + } + + System.out.print(5); + + + SetBlockQueue.addNotify(new Runnable() { + @Override + public void run() { + + System.out.print(6); + + pasteStates(schematic, plot, x_offset, z_offset); + + System.out.print(7); + + if (whenDone != null) { + whenDone.value = true; + whenDone.run(); + } + } + }); + return; + } catch (final Exception e) { + e.printStackTrace(); + TaskManager.runTask(whenDone); + return; } } - BlockManager.setBlocks(plot.world, xl, yl, zl, ids, data); - pasteStates(schematic, plot, x_offset, z_offset); - } catch (final Exception e) { - return false; - } - return true; + }); } public boolean pasteStates(final Schematic schematic, final Plot plot, final int x_offset, final int z_offset) { @@ -226,33 +336,42 @@ public abstract class SchematicHandler { public Schematic getSchematic(final CompoundTag tag, final File file) { final Map tagMap = tag.getValue(); - byte[] addId = new byte[0]; - if (tagMap.containsKey("AddBlocks")) { - addId = ByteArrayTag.class.cast(tagMap.get("AddBlocks")).getValue(); - } + // Slow +// byte[] addId = new byte[0]; +// if (tagMap.containsKey("AddBlocks")) { +// addId = ByteArrayTag.class.cast(tagMap.get("AddBlocks")).getValue(); +// } + // end slow + final short width = ShortTag.class.cast(tagMap.get("Width")).getValue(); final short length = ShortTag.class.cast(tagMap.get("Length")).getValue(); final short height = ShortTag.class.cast(tagMap.get("Height")).getValue(); - final byte[] b = ByteArrayTag.class.cast(tagMap.get("Blocks")).getValue(); - final byte[] d = ByteArrayTag.class.cast(tagMap.get("Data")).getValue(); - final short[] blocks = new short[b.length]; - final Dimension dimension = new Dimension(width, height, length); - for (int index = 0; index < b.length; index++) { - if ((index >> 1) >= addId.length) { - blocks[index] = (short) (b[index] & 0xFF); - } else { - if ((index & 1) == 0) { - blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (b[index] & 0xFF)); - } else { - blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (b[index] & 0xFF)); - } - } - } - final DataCollection[] collection = new DataCollection[b.length]; - for (int x = 0; x < b.length; x++) { - collection[x] = new DataCollection(blocks[x], d[x]); - } - Schematic schem = new Schematic(collection, dimension, file); + final byte[] block = ByteArrayTag.class.cast(tagMap.get("Blocks")).getValue(); + final byte[] data = ByteArrayTag.class.cast(tagMap.get("Data")).getValue(); + + // Slow + has code for exceptions (addId) inside the loop rather than outside +// for (int index = 0; index < b.length; index++) { +// if ((index >> 1) >= addId.length) { +// blocks[index] = (short) (b[index] & 0xFF); +// } else { +// if ((index & 1) == 0) { +// blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (b[index] & 0xFF)); +// } else { +// blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (b[index] & 0xFF)); +// } +// } +// } + // Slow as wrapper for each block +// final DataCollection[] collection = new DataCollection[b.length]; +// for (int x = 0; x < b.length; x++) { +// collection[x] = new DataCollection(blocks[x], d[x]); +// } +// Schematic schem = new Schematic(collection, dimension, file); + + Dimension dimensions = new Dimension(width, height, length); + Schematic schem = new Schematic(block, data, dimensions , file); + + // Slow try { List blockStates = ListTag.class.cast(tagMap.get("TileEntities")).getValue(); for (Tag stateTag : blockStates) { @@ -505,15 +624,44 @@ public abstract class SchematicHandler { * @author Citymonstret */ public class Schematic { - private final DataCollection[] blockCollection; + // Lossy but fast + private final byte[] ids; + private final byte[] datas; + + @Deprecated + private DataCollection[] collection; + private final Dimension schematicDimension; private final File file; private HashSet items; - public Schematic(final DataCollection[] blockCollection, final Dimension schematicDimension, final File file) { - this.blockCollection = blockCollection; - this.schematicDimension = schematicDimension; - this.file = file; + /** + * This is deprecated as having a wrapper for each block is really slow.
+ * - There's also a performance hit by having the cast the DataCollection short / byte + * - + * @param blockCollection + * @param schematicDimension + * @param file + */ +// @Deprecated +// public Schematic(final DataCollection[] blockCollection, final Dimension schematicDimension, final File file) { +// ids = new byte[blockCollection.length]; +// datas = new byte[blockCollection.length]; +// for (int i = 0; i < blockCollection.length; i++) { +// DataCollection block = blockCollection[i]; +// ids[i] = (byte) block.block; +// datas[i] = block.data; +// } +// this.collection = blockCollection; +// this.schematicDimension = schematicDimension; +// this.file = file; +// } + + public Schematic(final byte[] i, final byte[] b, final Dimension d, final File f) { + ids = i; + datas = b; + schematicDimension = d; + file = f; } public void addItem(PlotItem item) { @@ -534,10 +682,25 @@ public abstract class SchematicHandler { public Dimension getSchematicDimension() { return this.schematicDimension; } - - public DataCollection[] getBlockCollection() { - return this.blockCollection; + + public byte[] getIds() { + return ids; } + + public byte[] getDatas() { + return datas; + } + +// @Deprecated +// public DataCollection[] getBlockCollection() { +// if (this.collection == null) { +// collection = new DataCollection[ids.length]; +// for (int i = 0; i < ids.length; i++) { +// collection[i] = new DataCollection(ids[i], datas[i]); +// } +// } +// return this.collection; +// } } /**