From 577b19e2ae5c0bf315045163fe466bd8aeba9f80 Mon Sep 17 00:00:00 2001 From: boy0001 Date: Wed, 25 Feb 2015 23:25:28 +1100 Subject: [PATCH] Improved schematic exporting --- .../plot/commands/Claim.java | 11 +- .../plot/commands/MainCommand.java | 2 +- .../plot/commands/SchematicCmd.java | 327 ++++++++++++++++++ .../plot/generator/HybridPlotWorld.java | 6 +- .../plot/generator/HybridUtils.java | 8 +- .../plot/object/schematic/StateWrapper.java | 74 ++++ .../plot/util/BukkitSchematicHandler.java | 149 ++++++++ .../plot/util/SchematicHandler.java | 138 +------- 8 files changed, 582 insertions(+), 133 deletions(-) create mode 100644 PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java create mode 100644 PlotSquared/src/main/java/com/intellectualcrafters/plot/object/schematic/StateWrapper.java create mode 100644 PlotSquared/src/main/java/com/intellectualcrafters/plot/util/BukkitSchematicHandler.java diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Claim.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Claim.java index 1d3d154b9..646ea5bce 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Claim.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Claim.java @@ -31,6 +31,7 @@ import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.SchematicHandler; +import com.intellectualcrafters.plot.util.SchematicHandler.Schematic; /** * @author Citymonstret @@ -61,16 +62,16 @@ public class Claim extends SubCommand { final PlotWorld plotworld = PlotSquared.getPlotWorld(world); final Plot plot2 = PlotSquared.getPlots(world).get(plot.id); if (plotworld.SCHEMATIC_ON_CLAIM) { - SchematicHandler.Schematic sch; + Schematic sch; if (schematic.equals("")) { - sch = SchematicHandler.getSchematic(plotworld.SCHEMATIC_FILE); + sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE); } else { - sch = SchematicHandler.getSchematic(schematic); + sch = SchematicHandler.manager.getSchematic(schematic); if (sch == null) { - sch = SchematicHandler.getSchematic(plotworld.SCHEMATIC_FILE); + sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE); } } - SchematicHandler.paste(player.getLocation(), sch, plot2, 0, 0); + SchematicHandler.manager.paste(player.getLocation(), sch, plot2, 0, 0); } PlotSquared.getPlotManager(world).claimPlot(plotworld, plot); MainUtil.update(loc); diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java index 4f6b38354..574038289 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java @@ -40,7 +40,7 @@ public class MainCommand { /** * Main Permission Node */ - private final static SubCommand[] _subCommands = new SubCommand[] { new Template(), new Setup(), new DebugSaveTest(), new DebugLoadTest(), new CreateRoadSchematic(), new RegenAllRoads(), new DebugClear(), new Claim(), new Auto(), new Home(), new Visit(), new TP(), new Set(), new Clear(), new Delete(), new SetOwner(), new Denied(), new Helpers(), new Trusted(), new Info(), new list(), new Help(), new Debug(), new Schematic(), new plugin(), new Inventory(), new Purge(), new Reload(), new Merge(), new Unlink(), new Kick(), new Rate(), new DebugClaimTest(), new Inbox(), new Comment(), new Database(), new Unclaim(), new Swap(), new MusicSubcommand(), new DebugRoadRegen(), new Trim(), new DebugExec(), new FlagCmd(), new Target(), new DebugFixFlags(), new Move(), new Condense() }; + private final static SubCommand[] _subCommands = new SubCommand[] { new Template(), new Setup(), new DebugSaveTest(), new DebugLoadTest(), new CreateRoadSchematic(), new RegenAllRoads(), new DebugClear(), new Claim(), new Auto(), new Home(), new Visit(), new TP(), new Set(), new Clear(), new Delete(), new SetOwner(), new Denied(), new Helpers(), new Trusted(), new Info(), new list(), new Help(), new Debug(), new SchematicCmd(), new plugin(), new Inventory(), new Purge(), new Reload(), new Merge(), new Unlink(), new Kick(), new Rate(), new DebugClaimTest(), new Inbox(), new Comment(), new Database(), new Unclaim(), new Swap(), new MusicSubcommand(), new DebugRoadRegen(), new Trim(), new DebugExec(), new FlagCmd(), new Target(), new DebugFixFlags(), new Move(), new Condense() }; public final static ArrayList subCommands = new ArrayList() { { addAll(Arrays.asList(_subCommands)); diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java new file mode 100644 index 000000000..46692f8fd --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/SchematicCmd.java @@ -0,0 +1,327 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// +package com.intellectualcrafters.plot.commands; + +import java.util.Collection; +import java.util.HashMap; + +import com.intellectualcrafters.jnbt.CompoundTag; +import com.intellectualcrafters.plot.PlotSquared; +import com.intellectualcrafters.plot.config.C; +import com.intellectualcrafters.plot.config.Settings; +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.util.BlockManager; +import com.intellectualcrafters.plot.util.SchematicHandler; +import com.intellectualcrafters.plot.util.MainUtil; +import com.intellectualcrafters.plot.util.Permissions; +import com.intellectualcrafters.plot.util.SchematicHandler.DataCollection; +import com.intellectualcrafters.plot.util.SchematicHandler.Dimension; +import com.intellectualcrafters.plot.util.SchematicHandler.Schematic; +import com.intellectualcrafters.plot.util.TaskManager; +import com.intellectualcrafters.plot.util.bukkit.UUIDHandler; + +public class SchematicCmd extends SubCommand { + private int counter = 0; + private boolean running = false; + private Plot[] plots; + private int task; + + public SchematicCmd() { + super("schematic", "plots.schematic", "Schematic Command", "schematic {arg}", "sch", CommandCategory.ACTIONS, false); + // TODO command to fetch schematic from worldedit directory + } + + @Override + public boolean execute(final PlotPlayer plr, final String... args) { + if (args.length < 1) { + sendMessage(plr, C.SCHEMATIC_MISSING_ARG); + return true; + } + final String arg = args[0].toLowerCase(); + final String file; + final Schematic schematic; + switch (arg) { + case "paste": { + if (plr == null) { + PlotSquared.log(C.IS_CONSOLE.s()); + return false; + } + if (!Permissions.hasPermission(plr, "plots.schematic.paste")) { + MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.schematic.paste"); + return false; + } + if (args.length < 2) { + sendMessage(plr, C.SCHEMATIC_MISSING_ARG); + break; + } + final Location loc = plr.getLocation(); + final Plot plot = MainUtil.getPlot(loc); + if (plot == null) { + sendMessage(plr, C.NOT_IN_PLOT); + break; + } + if (this.running) { + MainUtil.sendMessage(plr, "&cTask is already running."); + return false; + } + final String file2 = args[1]; + this.running = true; + this.counter = 0; + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + 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 Location l1 = bot.add(0, sy - 1, 0); + final int WIDTH = schematic.getSchematicDimension().getX(); + final int LENGTH = schematic.getSchematicDimension().getZ(); + 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) { + sendMessage(plr, C.SCHEMATIC_PASTE_SUCCESS); + MainUtil.update(plr.getLocation()); + SchematicCmd.this.running = false; + PlotSquared.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); + } + }); + break; + } + case "test": { + if (plr == null) { + PlotSquared.log(C.IS_CONSOLE.s()); + return false; + } + if (!Permissions.hasPermission(plr, "plots.schematic.test")) { + MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.schematic.test"); + return false; + } + if (args.length < 2) { + sendMessage(plr, C.SCHEMATIC_MISSING_ARG); + break; + } + file = args[1]; + schematic = SchematicHandler.manager.getSchematic(file); + if (schematic == null) { + sendMessage(plr, C.SCHEMATIC_INVALID, "non-existent"); + break; + } + final Location loc = plr.getLocation(); + final int l1 = schematic.getSchematicDimension().getX(); + final int l2 = schematic.getSchematicDimension().getZ(); + final Plot plot = MainUtil.getPlot(loc); + final int length = MainUtil.getPlotWidth(loc.getWorld(), plot.id); + if ((l1 < length) || (l2 < length)) { + sendMessage(plr, C.SCHEMATIC_INVALID, String.format("Wrong size (x: %s, z: %d) vs %d ", l1, l2, length)); + break; + } + sendMessage(plr, C.SCHEMATIC_VALID); + break; + } + case "saveall": + case "exportall": { + if (plr != null) { + MainUtil.sendMessage(plr, C.NOT_CONSOLE); + return false; + } + if (args.length != 2) { + MainUtil.sendMessage(null, "&cNeed world arg. Use &7/plots sch exportall "); + return false; + } + final HashMap plotmap = PlotSquared.getPlots(args[1]); + if ((plotmap == null) || (plotmap.size() == 0)) { + MainUtil.sendMessage(null, "&cInvalid world. Use &7/plots sch exportall "); + return false; + } + if (this.running) { + MainUtil.sendMessage(null, "&cTask is already running."); + return false; + } + PlotSquared.log("&3PlotSquared&8->&3Schemaitc&8: &7Mass export has started. This may take a while."); + PlotSquared.log("&3PlotSquared&8->&3Schemaitc&8: &7Found &c" + plotmap.size() + "&7 plots..."); + final String worldname = args[1]; + final Collection values = plotmap.values(); + this.plots = values.toArray(new Plot[values.size()]); + this.running = true; + this.counter = 0; + this.task = TaskManager.runTaskRepeat(new Runnable() { + @Override + public void run() { + if (SchematicCmd.this.counter >= SchematicCmd.this.plots.length) { + PlotSquared.log("&3PlotSquared&8->&3Schemaitc&8: &aFinished!"); + SchematicCmd.this.running = false; + PlotSquared.TASK.cancelTask(SchematicCmd.this.task); + return; + } + final Plot plot = SchematicCmd.this.plots[SchematicCmd.this.counter]; + final CompoundTag sch = SchematicHandler.manager.getCompoundTag(worldname, plot.id); + final String o = UUIDHandler.getName(plot.owner); + final String owner = o == null ? "unknown" : o; + if (sch == null) { + MainUtil.sendMessage(null, "&7 - Skipped plot &c" + plot.id); + } else { + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + MainUtil.sendMessage(null, "&6ID: " + plot.id); + final boolean result = SchematicHandler.manager.save(sch, Settings.SCHEMATIC_SAVE_PATH + "/" + plot.id.x + ";" + plot.id.y + "," + worldname + "," + owner + ".schematic"); + if (!result) { + MainUtil.sendMessage(null, "&7 - Failed to save &c" + plot.id); + } else { + MainUtil.sendMessage(null, "&7 - &a success: " + plot.id); + } + } + }); + } + SchematicCmd.this.counter++; + } + }, 20); + break; + } + case "export": + case "save": { + if (!Permissions.hasPermission(plr, "plots.schematic.save")) { + MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.schematic.save"); + return false; + } + if (this.running) { + MainUtil.sendMessage(plr, "&cTask is already running."); + return false; + } + final String world; + final Plot p2; + if (plr != null) { + final Location loc = plr.getLocation(); + final Plot plot = MainUtil.getPlot(loc); + if (plot == null) { + return !sendMessage(plr, C.NOT_IN_PLOT); + } + if (!plot.isAdded(plr.getUUID())) { + sendMessage(plr, C.NO_PLOT_PERMS); + return false; + } + p2 = plot; + world = loc.getWorld(); + } else { + if (args.length == 3) { + try { + world = args[0]; + final String[] split = args[2].split(";"); + final PlotId i = new PlotId(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + if ((PlotSquared.getPlots(world) == null) || (PlotSquared.getPlots(world).get(i) == null)) { + MainUtil.sendMessage(null, "&cInvalid world or id. Use &7/plots sch save "); + return false; + } + p2 = PlotSquared.getPlots(world).get(i); + } catch (final Exception e) { + MainUtil.sendMessage(null, "&cInvalid world or id. Use &7/plots sch save "); + return false; + } + } else { + MainUtil.sendMessage(null, "&cInvalid world or id. Use &7/plots sch save "); + return false; + } + } + this.plots = new Plot[] { p2 }; + this.running = true; + this.counter = 0; + this.task = TaskManager.runTaskRepeat(new Runnable() { + @Override + public void run() { + if (SchematicCmd.this.counter >= SchematicCmd.this.plots.length) { + PlotSquared.log("&3PlotSquared&8->&3Schemaitc&8: &aFinished!"); + SchematicCmd.this.running = false; + PlotSquared.TASK.cancelTask(SchematicCmd.this.task); + return; + } + final Plot plot = SchematicCmd.this.plots[SchematicCmd.this.counter]; + final CompoundTag sch = SchematicHandler.manager.getCompoundTag(world, plot.id); + final String o = UUIDHandler.getName(plot.owner); + final String owner = o == null ? "unknown" : o; + if (sch == null) { + MainUtil.sendMessage(plr, "&7 - Skipped plot &c" + plot.id); + } else { + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + MainUtil.sendMessage(plr, "&6ID: " + plot.id); + final boolean result = SchematicHandler.manager.save(sch, Settings.SCHEMATIC_SAVE_PATH + "/" + plot.id.x + ";" + plot.id.y + "," + world + "," + owner.trim() + ".schematic"); + if (!result) { + MainUtil.sendMessage(plr, "&7 - Failed to save &c" + plot.id); + } else { + MainUtil.sendMessage(plr, "&7 - &aExport success: " + plot.id); + } + } + }); + } + SchematicCmd.this.counter++; + } + }, 60); + break; + } + default: { + sendMessage(plr, C.SCHEMATIC_MISSING_ARG); + break; + } + } + return true; + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java index ad0382fb8..c3fb50315 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java @@ -95,9 +95,9 @@ public class HybridPlotWorld extends ClassicPlotWorld { final String schem1Str = "GEN_ROAD_SCHEMATIC/" + this.worldname + "/sideroad"; final String schem2Str = "GEN_ROAD_SCHEMATIC/" + this.worldname + "/intersection"; final String schem3Str = "GEN_ROAD_SCHEMATIC/" + this.worldname + "/plot"; - final Schematic schem1 = SchematicHandler.getSchematic(schem1Str); - final Schematic schem2 = SchematicHandler.getSchematic(schem2Str); - final Schematic schem3 = SchematicHandler.getSchematic(schem3Str); + final Schematic schem1 = SchematicHandler.manager.getSchematic(schem1Str); + final Schematic schem2 = SchematicHandler.manager.getSchematic(schem2Str); + final Schematic schem3 = SchematicHandler.manager.getSchematic(schem3Str); final int shift = (int) Math.floor(this.ROAD_WIDTH / 2); int oddshift = 0; if ((this.ROAD_WIDTH % 2) != 0) { diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java index b0afc29d2..af85a6e89 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java @@ -72,11 +72,11 @@ public abstract class HybridUtils { final int ty = get_ey(world, bx, tx, bz, tz, by); final Location pos3 = new Location(world, bx, by, bz); final Location pos4 = new Location(world, tx, ty, tz); - final CompoundTag sideroad = SchematicHandler.getCompoundTag(world, pos1, pos2); - final CompoundTag intersection = SchematicHandler.getCompoundTag(world, pos3, pos4); + final CompoundTag sideroad = SchematicHandler.manager.getCompoundTag(world, pos1, pos2); + final CompoundTag intersection = SchematicHandler.manager.getCompoundTag(world, pos3, pos4); final String dir = PlotSquared.IMP.getDirectory() + File.separator + "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + plot.world + File.separator; - SchematicHandler.save(sideroad, dir + "sideroad.schematic"); - SchematicHandler.save(intersection, dir + "intersection.schematic"); + SchematicHandler.manager.save(sideroad, dir + "sideroad.schematic"); + SchematicHandler.manager.save(intersection, dir + "intersection.schematic"); plotworld.ROAD_SCHEMATIC_ENABLED = true; plotworld.setupSchematics(); return true; diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/schematic/StateWrapper.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/schematic/StateWrapper.java new file mode 100644 index 000000000..f98c3e075 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/schematic/StateWrapper.java @@ -0,0 +1,74 @@ +package com.intellectualcrafters.plot.object.schematic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.block.BlockState; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; + +import com.intellectualcrafters.jnbt.ByteTag; +import com.intellectualcrafters.jnbt.CompoundTag; +import com.intellectualcrafters.jnbt.ListTag; +import com.intellectualcrafters.jnbt.ShortTag; +import com.intellectualcrafters.jnbt.Tag; + +public class StateWrapper { + + public BlockState state; + + public StateWrapper(BlockState state) { + this.state = state; + } + + public CompoundTag getTag() { + if (state instanceof InventoryHolder) { + InventoryHolder inv = (InventoryHolder) state; + ItemStack[] contents = inv.getInventory().getContents(); + Map values = new HashMap(); + values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(contents))); + return new CompoundTag(values); + } + return null; + } + + public String getId() { + return "Chest"; + } + + public List serializeInventory(ItemStack[] items) { + List tags = new ArrayList(); + for (int i = 0; i < items.length; ++i) { + if (items[i] != null) { + Map tagData = serializeItem(items[i]); + tagData.put("Slot", new ByteTag("Slot", (byte) i)); + tags.add(new CompoundTag(tagData)); + } + } + return tags; + } + + public Map serializeItem(ItemStack item) { + Map data = new HashMap(); + data.put("id", new ShortTag("id", (short) item.getTypeId())); + data.put("Damage", new ShortTag("Damage", item.getDurability())); + data.put("Count", new ByteTag("Count", (byte) item.getAmount())); + if (!item.getEnchantments().isEmpty()) { + List enchantmentList = new ArrayList(); + for(Entry entry : item.getEnchantments().entrySet()) { + Map enchantment = new HashMap(); + enchantment.put("id", new ShortTag("id", (short) entry.getKey().getId())); + enchantment.put("lvl", new ShortTag("lvl", entry.getValue().shortValue())); + enchantmentList.add(new CompoundTag(enchantment)); + } + Map auxData = new HashMap(); + auxData.put("ench", new ListTag("ench", CompoundTag.class, enchantmentList)); + data.put("tag", new CompoundTag("tag", auxData)); + } + return data; + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/BukkitSchematicHandler.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/BukkitSchematicHandler.java new file mode 100644 index 000000000..ceb53ae53 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/BukkitSchematicHandler.java @@ -0,0 +1,149 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// +package com.intellectualcrafters.plot.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; + +import com.intellectualcrafters.jnbt.ByteArrayTag; +import com.intellectualcrafters.jnbt.CompoundTag; +import com.intellectualcrafters.jnbt.IntTag; +import com.intellectualcrafters.jnbt.ListTag; +import com.intellectualcrafters.jnbt.ShortTag; +import com.intellectualcrafters.jnbt.StringTag; +import com.intellectualcrafters.jnbt.Tag; +import com.intellectualcrafters.plot.PlotSquared; +import com.intellectualcrafters.plot.object.ChunkLoc; +import com.intellectualcrafters.plot.object.Location; +import com.intellectualcrafters.plot.object.schematic.StateWrapper; + +/** + * Schematic Handler + * + * @author Citymonstret + * @author Empire92 + */ +public class BukkitSchematicHandler extends SchematicHandler { + + @Override + public CompoundTag getCompoundTag(final String world, final Location pos1, final Location pos2) { + // loading chunks + int i = 0; + int j = 0; + try { + for (i = (pos1.getX() / 16) * 16; i < (16 + ((pos2.getX() / 16) * 16)); i += 16) { + for (j = (pos1.getZ() / 16) * 16; j < (16 + ((pos2.getZ() / 16) * 16)); j += 16) { + boolean result = ChunkManager.manager.loadChunk(world, new ChunkLoc(i, j)); + if (!result) { + return null; + } + } + } + } catch (final Exception e) { + PlotSquared.log("&7 - Cannot save: corrupt chunk at " + (i / 16) + ", " + (j / 16)); + return null; + } + final int width = (pos2.getX() - pos1.getX()) + 1; + final int height = (pos2.getY() - pos1.getY()) + 1; + final int length = (pos2.getZ() - pos1.getZ()) + 1; + final HashMap schematic = new HashMap<>(); + schematic.put("Width", new ShortTag("Width", (short) width)); + schematic.put("Length", new ShortTag("Length", (short) length)); + schematic.put("Height", new ShortTag("Height", (short) height)); + schematic.put("Materials", new StringTag("Materials", "Alpha")); + schematic.put("WEOriginX", new IntTag("WEOriginX", 0)); + schematic.put("WEOriginY", new IntTag("WEOriginY", 0)); + schematic.put("WEOriginZ", new IntTag("WEOriginZ", 0)); + schematic.put("WEOffsetX", new IntTag("WEOffsetX", 0)); + schematic.put("WEOffsetY", new IntTag("WEOffsetY", 0)); + schematic.put("WEOffsetZ", new IntTag("WEOffsetZ", 0)); + final byte[] blocks = new byte[width * height * length]; + byte[] addBlocks = null; + final byte[] blockData = new byte[width * height * length]; + final int sx = pos1.getX(); + pos2.getX(); + final int sz = pos1.getZ(); + pos2.getZ(); + final int sy = pos1.getY(); + pos2.getY(); + + List tileEntities = new ArrayList(); + + World worldObj = Bukkit.getWorld(world); + + 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; + + Block block = worldObj.getBlockAt(sx + x, sy + y, sz + z); + BlockState state = block.getState(); + if (state != null) { + StateWrapper wrapper = new StateWrapper(state); + CompoundTag rawTag = wrapper.getTag(); + if (rawTag != null) { + Map values = new HashMap(); + for (Entry entry : rawTag.getValue().entrySet()) { + values.put(entry.getKey(), entry.getValue()); + } + values.put("id", new StringTag("id", wrapper.getId())); + values.put("x", new IntTag("x", x)); + values.put("y", new IntTag("y", y)); + values.put("z", new IntTag("z", z)); + CompoundTag tileEntityTag = new CompoundTag(values); + tileEntities.add(tileEntityTag); + } + } + int id = block.getTypeId(); + byte data = block.getData(); + if (id > 255) { + if (addBlocks == null) { + addBlocks = new byte[(blocks.length >> 1) + 1]; + } + addBlocks[index >> 1] = (byte) (((index & 1) == 0) ? (addBlocks[index >> 1] & 0xF0) | ((id >> 8) & 0xF) : (addBlocks[index >> 1] & 0xF) | (((id >> 8) & 0xF) << 4)); + } + blocks[index] = (byte) id; + blockData[index] = data; + } + } + } + + schematic.put("Blocks", new ByteArrayTag("Blocks", blocks)); + schematic.put("Data", new ByteArrayTag("Data", blockData)); + schematic.put("Entities", new ListTag("Entities", CompoundTag.class, new ArrayList())); + schematic.put("TileEntities", new ListTag("TileEntities", CompoundTag.class, tileEntities)); + + if (addBlocks != null) { + schematic.put("AddBlocks", new ByteArrayTag("AddBlocks", addBlocks)); + } + return new CompoundTag("Schematic", schematic); + } + + +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java index 596435a46..10d37e81d 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java @@ -1,23 +1,3 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////// -// PlotSquared - A plot manager and world generator for the Bukkit API / -// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / -// / -// This program is free software; you can redistribute it and/or modify / -// it under the terms of the GNU General Public License as published by / -// the Free Software Foundation; either version 3 of the License, or / -// (at your option) any later version. / -// / -// This program is distributed in the hope that it will be useful, / -// but WITHOUT ANY WARRANTY; without even the implied warranty of / -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / -// GNU General Public License for more details. / -// / -// You should have received a copy of the GNU General Public License / -// along with this program; if not, write to the Free Software Foundation, / -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / -// / -// You can contact us via: support@intellectualsites.com / -//////////////////////////////////////////////////////////////////////////////////////////////////// package com.intellectualcrafters.plot.util; import java.io.File; @@ -26,37 +6,25 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Map; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import org.bukkit.Chunk; - import com.intellectualcrafters.jnbt.ByteArrayTag; import com.intellectualcrafters.jnbt.CompoundTag; -import com.intellectualcrafters.jnbt.IntTag; -import com.intellectualcrafters.jnbt.ListTag; import com.intellectualcrafters.jnbt.NBTInputStream; import com.intellectualcrafters.jnbt.NBTOutputStream; import com.intellectualcrafters.jnbt.ShortTag; -import com.intellectualcrafters.jnbt.StringTag; import com.intellectualcrafters.jnbt.Tag; import com.intellectualcrafters.plot.PlotSquared; 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.util.bukkit.BukkitUtil; -/** - * Schematic Handler - * - * @author Citymonstret - * @author Empire92 - */ -public class SchematicHandler { +public abstract class SchematicHandler { + public static SchematicHandler manager = new BukkitSchematicHandler(); + /** * Paste a schematic * @@ -66,7 +34,7 @@ public class SchematicHandler { * * @return true if succeeded */ - public static boolean paste(final Location location, final Schematic schematic, final Plot plot, final int x_offset, final int z_offset) { + public boolean paste(final Location location, final Schematic schematic, final Plot plot, final int x_offset, final int z_offset) { if (schematic == null) { PlotSquared.log("Schematic == null :|"); return false; @@ -109,7 +77,7 @@ public class SchematicHandler { return true; } - public static Schematic getSchematic(final CompoundTag tag, final File file) { + public Schematic getSchematic(final CompoundTag tag, final File file) { final Map tagMap = tag.getValue(); byte[] addId = new byte[0]; if (tagMap.containsKey("AddBlocks")) { @@ -140,7 +108,7 @@ public class SchematicHandler { } return new Schematic(collection, dimension, file); } - + /** * Get a schematic * @@ -148,7 +116,7 @@ public class SchematicHandler { * * @return schematic if found, else null */ - public static Schematic getSchematic(final String name) { + public Schematic getSchematic(final String name) { { final File parent = new File(PlotSquared.IMP.getDirectory() + File.separator + "schematics"); if (!parent.exists()) { @@ -173,7 +141,7 @@ public class SchematicHandler { return null; } } - + /** * Saves a schematic to a file path * @@ -182,7 +150,7 @@ public class SchematicHandler { * * @return true if succeeded */ - public static boolean save(final CompoundTag tag, final String path) { + public boolean save(final CompoundTag tag, final String path) { if (tag == null) { PlotSquared.log("&cCannot save empty tag"); return false; @@ -201,7 +169,7 @@ public class SchematicHandler { } return true; } - + /** * Gets the schematic of a plot * @@ -210,7 +178,7 @@ public class SchematicHandler { * * @return tag */ - public static CompoundTag getCompoundTag(final String world, final PlotId id) { + public CompoundTag getCompoundTag(final String world, final PlotId id) { if (!PlotSquared.getPlots(world).containsKey(id)) { return null; } @@ -218,80 +186,10 @@ public class SchematicHandler { final Location pos2 = MainUtil.getPlotTopLoc(world, id); return getCompoundTag(world, pos1, pos2); } - - @SuppressWarnings("deprecation") - public static CompoundTag getCompoundTag(final String world, final Location pos1, final Location pos2) { - // loading chunks - int i = 0; - int j = 0; - try { - for (i = (pos1.getX() / 16) * 16; i < (16 + ((pos2.getX() / 16) * 16)); i += 16) { - for (j = (pos1.getZ() / 16) * 16; j < (16 + ((pos2.getZ() / 16) * 16)); j += 16) { - final Chunk chunk = BukkitUtil.getChunkAt(world, i, j); - final boolean result = chunk.load(false); - if (!result) { - // Plot is not even generated - return null; - } - } - } - } catch (final Exception e) { - PlotSquared.log("&7 - Cannot save: corrupt chunk at " + (i / 16) + ", " + (j / 16)); - return null; - } - final int width = (pos2.getX() - pos1.getX()) + 1; - final int height = (pos2.getY() - pos1.getY()) + 1; - final int length = (pos2.getZ() - pos1.getZ()) + 1; - final HashMap schematic = new HashMap<>(); - schematic.put("Width", new ShortTag("Width", (short) width)); - schematic.put("Length", new ShortTag("Length", (short) length)); - schematic.put("Height", new ShortTag("Height", (short) height)); - schematic.put("Materials", new StringTag("Materials", "Alpha")); - schematic.put("WEOriginX", new IntTag("WEOriginX", 0)); - schematic.put("WEOriginY", new IntTag("WEOriginY", 0)); - schematic.put("WEOriginZ", new IntTag("WEOriginZ", 0)); - schematic.put("WEOffsetX", new IntTag("WEOffsetX", 0)); - schematic.put("WEOffsetY", new IntTag("WEOffsetY", 0)); - schematic.put("WEOffsetZ", new IntTag("WEOffsetZ", 0)); - final byte[] blocks = new byte[width * height * length]; - byte[] addBlocks = null; - final byte[] blockData = new byte[width * height * length]; - final int sx = pos1.getX(); - pos2.getX(); - final int sz = pos1.getZ(); - pos2.getZ(); - final int sy = pos1.getY(); - pos2.getY(); - 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 PlotBlock block = BukkitUtil.getBlock(new Location(world, sx + x, sy + y, sz + z)); - if (block.id > 255) { - if (addBlocks == null) { - addBlocks = new byte[(blocks.length >> 1) + 1]; - } - addBlocks[index >> 1] = (byte) (((index & 1) == 0) ? (addBlocks[index >> 1] & 0xF0) | ((block.id >> 8) & 0xF) : (addBlocks[index >> 1] & 0xF) | (((block.id >> 8) & 0xF) << 4)); - } - blocks[index] = (byte) block.id; - blockData[index] = block.data; - // We need worldedit to save tileentity data or entities - // - it uses NMS and CB internal code, which changes every - // update - } - } - } - schematic.put("Blocks", new ByteArrayTag("Blocks", blocks)); - schematic.put("Data", new ByteArrayTag("Data", blockData)); - schematic.put("Entities", new ListTag("Entities", CompoundTag.class, new ArrayList())); - schematic.put("TileEntities", new ListTag("TileEntities", CompoundTag.class, new ArrayList())); - if (addBlocks != null) { - schematic.put("AddBlocks", new ByteArrayTag("AddBlocks", addBlocks)); - } - return new CompoundTag("Schematic", schematic); - } - - public static boolean pastePart(final String world, final DataCollection[] blocks, final Location l1, final int x_offset, final int z_offset, final int i1, final int i2, final int WIDTH, final int LENGTH) { + + public abstract CompoundTag getCompoundTag(final String world, final Location pos1, final Location pos2); + + public boolean pastePart(final String world, final DataCollection[] blocks, final Location l1, final int x_offset, final int z_offset, final int i1, final int i2, final int WIDTH, final int LENGTH) { int length = 0; for (int i = i1; i <= i2; i++) { if (blocks[i].block == 0) { @@ -334,7 +232,7 @@ public class SchematicHandler { * * @author Citymonstret */ - public static class Schematic { + public class Schematic { private final DataCollection[] blockCollection; private final Dimension schematicDimension; private final File file; @@ -363,7 +261,7 @@ public class SchematicHandler { * * @author Citymonstret */ - public static class Dimension { + public class Dimension { private final int x; private final int y; private final int z; @@ -392,7 +290,7 @@ public class SchematicHandler { * * @author Citymonstret */ - public static class DataCollection { + public class DataCollection { private final short block; private final byte data;