diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 4a7c4b2be..b6cd5af3d 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -162,6 +162,22 @@ public class BukkitUtil extends WorldUtil { return new Location(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), temp.getYaw(), temp.getPitch()); } + @Override + public void setSpawn(Location loc) { + World world = getWorld(loc.getWorld()); + if (world != null) { + world.setSpawnLocation(loc.getX(), loc.getY(), loc.getZ()); + } + } + + @Override + public void saveWorld(String worldname) { + World world = getWorld(worldname); + if (world != null) { + world.save(); + } + } + @Override public int getHighestBlock(final String world, final int x, final int z) { return getWorld(world).getHighestBlockAt(x, z).getY(); diff --git a/Core/src/main/java/com/intellectualcrafters/plot/commands/Download.java b/Core/src/main/java/com/intellectualcrafters/plot/commands/Download.java index 5f9c6064b..a27d11c31 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/commands/Download.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/commands/Download.java @@ -8,15 +8,16 @@ import com.intellectualcrafters.plot.flag.FlagManager; import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.RunnableVal; +import com.intellectualcrafters.plot.util.BO3Handler; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.SchematicHandler; -import com.intellectualcrafters.plot.util.TaskManager; +import com.intellectualcrafters.plot.util.StringMan; +import com.intellectualcrafters.plot.util.WorldUtil; import com.plotsquared.general.commands.CommandDeclaration; - import java.net.URL; -@CommandDeclaration(command = "download", aliases = { "dl" }, category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE, description = "Download your plot", permission = "plots.download") +@CommandDeclaration(usage = "/plot download [schematic|bo3|world]", command = "download", aliases = { "dl" }, category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE, description = "Download your plot", permission = "plots.download") public class Download extends SubCommand { @Override @@ -41,26 +42,63 @@ public class Download extends SubCommand { MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER); return false; } - plot.addRunning(); - MainUtil.sendMessage(plr, C.GENERATING_LINK); - SchematicHandler.manager.getCompoundTag(plot, new RunnableVal() { - @Override - public void run(final CompoundTag value) { - TaskManager.runTaskAsync(new Runnable() { - @Override - public void run() { - final URL url = SchematicHandler.manager.upload(value, null, null); - if (url == null) { - MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED); - plot.removeRunning(); - return; + if (args.length == 0 || (args.length == 1 && StringMan.isEqualIgnoreCaseToAny(args[0], "sch", "schem", "schematic"))) { + plot.addRunning(); + SchematicHandler.manager.getCompoundTag(plot, new RunnableVal() { + @Override + public void run(final CompoundTag value) { + plot.removeRunning(); + SchematicHandler.manager.upload(value, null, null, new RunnableVal() { + @Override + public void run(URL url) { + if (url == null) { + MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED); + return; + } + MainUtil.sendMessage(plr, url.toString()); } - MainUtil.sendMessage(plr, url.toString()); - plot.removeRunning(); - } - }); + }); + } + }); + } else if (args.length == 1 && StringMan.isEqualIgnoreCaseToAny(args[0], "bo3", "bo2", "b03", "b02")) { + if (!Permissions.hasPermission(plr, "plots.download.bo3")) { + C.NO_PERMISSION.send(plr, "plots.download.bo3"); } - }); + plot.addRunning(); + BO3Handler.upload(plot, null, null, new RunnableVal() { + @Override + public void run(URL url) { + plot.removeRunning(); + if (url == null) { + MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED); + return; + } + MainUtil.sendMessage(plr, url.toString()); + } + }); + } else if (args.length == 1 && StringMan.isEqualIgnoreCaseToAny(args[0], "mcr", "world", "mca")) { + if (!Permissions.hasPermission(plr, "plots.download.world")) { + C.NO_PERMISSION.send(plr, "plots.download.world"); + } + MainUtil.sendMessage(plr, "&cNote: The `.mca` files are 512x512"); + plot.addRunning(); + WorldUtil.IMP.upload(plot, null, null, new RunnableVal() { + @Override + public void run(URL url) { + plot.removeRunning(); + if (url == null) { + MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED); + return; + } + MainUtil.sendMessage(plr, url.toString()); + } + }); + } + else { + C.COMMAND_SYNTAX.send(plr, getUsage()); + return false; + } + MainUtil.sendMessage(plr, C.GENERATING_LINK); return true; } } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java b/Core/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java index c337b673e..4d647cb44 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/commands/MainCommand.java @@ -374,13 +374,13 @@ public class MainCommand extends CommandManager { // ex. /p h:2 SomeUsername // > /p h SomeUsername 2 String[] temp = label.split(":"); - label = temp[0]; - - String[] tempArgs = new String[args.length + 1]; - System.arraycopy(args, 0, tempArgs, 0, args.length); - tempArgs[tempArgs.length - 1] = temp[1]; - - args = tempArgs; + if (temp.length == 2) { + label = temp[0]; + String[] tempArgs = new String[args.length + 1]; + System.arraycopy(args, 0, tempArgs, 0, args.length); + tempArgs[tempArgs.length - 1] = temp[1]; + args = tempArgs; + } } cmd = getInstance().commands.get(label.toLowerCase()); } else { diff --git a/Core/src/main/java/com/intellectualcrafters/plot/commands/Save.java b/Core/src/main/java/com/intellectualcrafters/plot/commands/Save.java index 5e2cfa013..31fda1af0 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/commands/Save.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/commands/Save.java @@ -64,19 +64,21 @@ public class Save extends SubCommand { final String world = plot.getArea().toString().replaceAll(";", "-").replaceAll("[^A-Za-z0-9]", ""); final String file = time + "_" + world + "_" + id.x + "_" + id.y + "_" + size + "_" + name; final UUID uuid = plr.getUUID(); - - final URL url = SchematicHandler.manager.upload(value, uuid, file); - if (url == null) { - MainUtil.sendMessage(plr, C.SAVE_FAILED); - plot.removeRunning(); - return; - } - MainUtil.sendMessage(plr, C.SAVE_SUCCESS); - final List schematics = (List) plr.getMeta("plot_schematics"); - if (schematics != null) { - schematics.add(file); - } - plot.removeRunning(); + SchematicHandler.manager.upload(value, uuid, file, new RunnableVal() { + @Override + public void run(URL url) { + plot.removeRunning(); + if (url == null) { + MainUtil.sendMessage(plr, C.SAVE_FAILED); + return; + } + MainUtil.sendMessage(plr, C.SAVE_SUCCESS); + final List schematics = (List) plr.getMeta("plot_schematics"); + if (schematics != null) { + schematics.add(file); + } + } + }); } }); } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/commands/Visit.java b/Core/src/main/java/com/intellectualcrafters/plot/commands/Visit.java index c7305e87c..d549900a1 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/commands/Visit.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/commands/Visit.java @@ -30,8 +30,12 @@ import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.UUIDHandler; import com.plotsquared.general.commands.Argument; import com.plotsquared.general.commands.CommandDeclaration; - -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; @CommandDeclaration( command = "visit", @@ -82,8 +86,6 @@ public class Visit extends SubCommand { } if (user != null) { unsorted = PS.get().getBasePlots(user); - } else if (PS.get().getPlotAreaByString(args[0]) != null) { - unsorted = PS.get().getPlotAreaByString(args[0]).getPlots(); } else { final Plot plot = MainUtil.getPlotFromString(player, args[0], true); if (plot != null) { diff --git a/Core/src/main/java/com/intellectualcrafters/plot/object/BO3.java b/Core/src/main/java/com/intellectualcrafters/plot/object/BO3.java index 8044e17d3..66b733c36 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/object/BO3.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/object/BO3.java @@ -1,12 +1,19 @@ package com.intellectualcrafters.plot.object; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.util.MainUtil; +import java.io.File; + public class BO3 { private final ChunkLoc chunk; + private final String world; private final StringBuilder blocks; private final StringBuilder children; private final String name; - public BO3(final String name, final ChunkLoc loc) { + public BO3(final String name, final String world, final ChunkLoc loc) { + this.world = world; this.name = name; chunk = loc; blocks = new StringBuilder(); @@ -21,6 +28,10 @@ public class BO3 { public ChunkLoc getLoc() { return chunk; } + + public String getWorld() { + return world; + } public String getName() { return name; @@ -42,4 +53,12 @@ public class BO3 { public String getChildren() { return children.toString(); } + + public File getFile() { + return MainUtil.getFile(PS.get().IMP.getDirectory(), Settings.BO3_SAVE_PATH + File.separator + getWorld() + File.separator + getFilename()); + } + + public String getFilename() { + return name + (((chunk.x == 0) && (chunk.z == 0)) ? "" : ("_" + chunk.x + "_" + chunk.z)) + ".bo3"; + } } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/object/BlockLoc.java b/Core/src/main/java/com/intellectualcrafters/plot/object/BlockLoc.java index 7d2f95a15..cc0f02611 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/object/BlockLoc.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/object/BlockLoc.java @@ -36,7 +36,7 @@ public class BlockLoc { return true; } if (obj == null) { - return false; + return x == 0 && y == 0 && z == 0; } if (getClass() != obj.getClass()) { return false; @@ -47,7 +47,11 @@ public class BlockLoc { @Override public String toString() { + if (x == 0 && y == 0 && z == 0) { + return ""; + } return x + "," + y + "," + z + "," + yaw + "," + pitch; + } public static BlockLoc fromString(final String string) { diff --git a/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java b/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java index 9626ce6d8..ffb1f5d7d 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java @@ -564,43 +564,42 @@ public class Plot { * @return true if merged in that direction */ public boolean getMerged(final int direction) { - if (isMerged()) { - switch (direction) { - case 0: - case 1: - case 2: - case 3: - return this.getSettings().getMerged(direction); - case 7: - int i = direction - 4; - int i2 = 0; - if (this.getSettings().getMerged(i2)) { - if (this.getSettings().getMerged(i)) { - if (this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)) { - if (this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i)) { - return true; - } + if (settings == null) { + return false; + } + switch (direction) { + case 0: + case 1: + case 2: + case 3: + return this.getSettings().getMerged(direction); + case 7: + int i = direction - 4; + int i2 = 0; + if (this.getSettings().getMerged(i2)) { + if (this.getSettings().getMerged(i)) { + if (this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)) { + if (this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i)) { + return true; } } } - return false; - case 4: - case 5: - case 6: - i = direction - 4; - i2 = direction - 3; - return this.getSettings().getMerged(i2) - && this.getSettings().getMerged(i) - && this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2) - && this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i); + } + return false; + case 4: + case 5: + case 6: + i = direction - 4; + i2 = direction - 3; + return this.getSettings().getMerged(i2) + && this.getSettings().getMerged(i) + && this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2) + && this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i); - } - return false; - } else { - return false; } + return false; } - + /** * Get the denied users * @return @@ -1129,13 +1128,13 @@ public class Plot { * @param loc */ public void setHome(final BlockLoc loc) { - final BlockLoc pos = this.getSettings().getPosition(); - if (pos.equals(new BlockLoc(0, 0, 0)) && loc == null || pos.equals(loc)) { + final Plot plot = this.getBasePlot(false); + final BlockLoc pos = plot.getSettings().getPosition(); + if (new BlockLoc(0, 0, 0).equals(loc)) { return; } - final Plot plot = this.getBasePlot(false); plot.getSettings().setPosition(loc); - DBFunc.setPosition(plot, this.getSettings().getPosition().toString()); + DBFunc.setPosition(plot, plot.getSettings().getPosition().toString()); } /** @@ -1761,27 +1760,40 @@ public class Plot { } /** - * Upload the plot as a schematic to the configured web interface + * Upload the plot as a schematic to the configured web interface
* @param whenDone value will be null if uploading fails */ public void upload(final RunnableVal whenDone) { SchematicHandler.manager.getCompoundTag(this, new RunnableVal() { @Override public void run(final CompoundTag value) { - TaskManager.runTaskAsync(new Runnable() { - @Override - public void run() { - final URL url = SchematicHandler.manager.upload(value, null, null); - if (whenDone != null) { - whenDone.value = url; - } - TaskManager.runTask(whenDone); - } - }); + SchematicHandler.manager.upload(value, null, null, whenDone); } }); } + /** + * Upload this plot as a world file
+ * - The mca files are each 512x512, so depending on the plot size it may also download adjacent plots
+ * - Works best when (plot width + road width) % 512 == 0
+ * @see com.intellectualcrafters.plot.util.WorldUtil + * @param whenDone + */ + public void uploadWorld(RunnableVal whenDone) { + WorldUtil.IMP.upload(this, null, null, whenDone); + } + + /** + * Upload this plot as a BO3
+ * - May not work on non default generator
+ * - BO3 includes flags/ignores plot main/floor block
+ * @see com.intellectualcrafters.plot.util.BO3Handler + * @param whenDone + */ + public void uploadBO3(RunnableVal whenDone) { + BO3Handler.upload(this, null, null, whenDone); + } + @Override public boolean equals(final Object obj) { if (this == obj) { diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/BO3Handler.java b/Core/src/main/java/com/intellectualcrafters/plot/util/BO3Handler.java index 2cefac90d..6ce0a9a9d 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/BO3Handler.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/BO3Handler.java @@ -12,8 +12,13 @@ import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.RegionWrapper; - +import com.intellectualcrafters.plot.object.RunnableVal; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardOpenOption; @@ -22,17 +27,29 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; +import java.util.UUID; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; public class BO3Handler { /** - * @see #saveBO3(PlotPlayer, Plot) + * @see #saveBO3(PlotPlayer, Plot, RunnableVal) * @param plot * @return if successfully exported */ public static boolean saveBO3(final Plot plot) { return saveBO3(null, plot); } + + public static boolean saveBO3(final PlotPlayer player, final Plot plot) { + return saveBO3(player, plot, new RunnableVal() { + @Override + public void run(BO3 bo3) { + save(plot, bo3); + } + }); + } public static boolean contains(final PlotBlock[] blocks, final PlotBlock block) { for (final PlotBlock item : blocks) { @@ -50,7 +67,10 @@ public class BO3Handler { * @param plot * @return */ - public static boolean saveBO3(final PlotPlayer plr, final Plot plot) { + public static boolean saveBO3(final PlotPlayer plr, final Plot plot, RunnableVal saveTask) { + if (saveTask == null) { + throw new IllegalArgumentException("Save task cannot be null!"); + } final PlotArea plotworld = plot.getArea(); if (!(plotworld instanceof ClassicPlotWorld) || (plotworld.TYPE != 0)) { MainUtil.sendMessage(plr, "BO3 exporting only supports type 0 classic generation."); @@ -83,8 +103,8 @@ public class BO3Handler { boolean content = false; for (RegionWrapper region : regions) { - Location pos1 = new Location(plot.getArea().worldname, region.minX, region.minY, region.minZ); - Location pos2 = new Location(plot.getArea().worldname, region.maxX, region.maxY, region.maxZ); + Location pos1 = new Location(plotworld.worldname, region.minX, region.minY, region.minZ); + Location pos2 = new Location(plotworld.worldname, region.maxX, region.maxY, region.maxZ); for (int x = pos1.getX(); x <= pos2.getX(); x++) { final int X = ((x + 7) - cx) >> 4; final int xx = (x - cx) % 16; @@ -97,7 +117,7 @@ public class BO3Handler { final PlotBlock block = WorldUtil.IMP.getBlock(new Location(plot.getArea().worldname, x, y, z)); if (!contains(cpw.MAIN_BLOCK, block)) { if (bo3 == null) { - bo3 = new BO3(alias, loc); + bo3 = new BO3(alias, plotworld.worldname, loc); map.put(loc, bo3); content = true; } @@ -107,7 +127,7 @@ public class BO3Handler { final PlotBlock floor = WorldUtil.IMP.getBlock(new Location(plot.getArea().worldname, x, height, z)); if (!contains(cpw.TOP_BLOCK, floor)) { if (bo3 == null) { - bo3 = new BO3(alias, loc); + bo3 = new BO3(alias, plotworld.worldname, loc); map.put(loc, bo3); content = true; } @@ -117,7 +137,7 @@ public class BO3Handler { final PlotBlock block = WorldUtil.IMP.getBlock(new Location(plot.getArea().worldname, x, y, z)); if (block.id != 0) { if (bo3 == null) { - bo3 = new BO3(alias, loc); + bo3 = new BO3(alias, plotworld.worldname, loc); map.put(loc, bo3); content = true; } @@ -164,14 +184,78 @@ public class BO3Handler { } for (final Entry entry : map.entrySet()) { - save(plot, entry.getValue()); + saveTask.run(entry.getValue()); } MainUtil.sendMessage(plr, "BO3 exporting was successful!"); return true; } - + + public static void upload(final Plot plot, final UUID uuid, final String file, final RunnableVal whenDone) { + if (plot == null) { + throw new IllegalArgumentException("Arguments may not be null!"); + } + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (final ZipOutputStream zos = new ZipOutputStream(baos)) { + saveBO3(null, plot, new RunnableVal() { + @Override + public void run(BO3 bo3) { + try { + final ZipEntry ze = new ZipEntry(bo3.getFilename()); + zos.putNextEntry(ze); + write(zos, plot, bo3); + zos.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } + catch (IOException e) { + e.printStackTrace(); + whenDone.run(); + return; + } + MainUtil.upload(uuid, file, "zip", new RunnableVal() { + @Override + public void run(OutputStream output) { + try { + output.write(baos.toByteArray()); + baos.flush(); + baos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }, whenDone); + } + + public static void write(OutputStream stream, final Plot plot, BO3 bo3) throws IOException { + File base = getBaseFile(bo3.getWorld()); + final List lines = Files.readAllLines(base.toPath(), StandardCharsets.UTF_8); + for (int i = 0; i < lines.size(); i++) { + final String line = lines.get(i).trim(); + final String result = StringMan.replaceAll(line, "%owner%", MainUtil.getName(plot.owner), "%alias%", plot.toString(), "%blocks%", bo3.getBlocks(), "%branches%", bo3.getChildren(), + "%flags%", StringMan.join(FlagManager.getPlotFlags(plot).values(), ",")); + if (!StringMan.isEqual(result, line)) { + lines.set(i, result); + } + } + stream.write(StringMan.join(lines, System.getProperty("line.separator")).getBytes()); + } + public static boolean save(final Plot plot, final BO3 bo3) { + try { + File bo3File = bo3.getFile(); + bo3File.createNewFile(); + try (FileOutputStream fos = new FileOutputStream(bo3File)) { + write(fos, plot, bo3); + } + } catch (final Exception e) { + e.printStackTrace(); + return false; + } + final File base = getBaseFile(plot.getArea().worldname); try { final List lines = Files.readAllLines(base.toPath(), StandardCharsets.UTF_8); diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java b/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java index 75948b901..7dc12c94b 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java @@ -26,12 +26,35 @@ import com.intellectualcrafters.plot.config.Settings; import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.flag.Flag; import com.intellectualcrafters.plot.flag.FlagManager; -import com.intellectualcrafters.plot.object.*; - +import com.intellectualcrafters.plot.object.ChunkLoc; +import com.intellectualcrafters.plot.object.ConsolePlayer; +import com.intellectualcrafters.plot.object.Location; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotArea; +import com.intellectualcrafters.plot.object.PlotBlock; +import com.intellectualcrafters.plot.object.PlotId; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.object.PseudoRandom; +import com.intellectualcrafters.plot.object.RegionWrapper; +import com.intellectualcrafters.plot.object.RunnableVal; import java.io.File; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; import java.nio.file.Paths; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.UUID; import java.util.regex.Matcher; /** @@ -106,6 +129,86 @@ public class MainUtil { } } + public static void upload(UUID uuid, String file, String extension, final RunnableVal writeTask, final RunnableVal whenDone) { + if (writeTask == null) { + PS.debug("&cWrite task cannot be null"); + TaskManager.runTask(whenDone); + return; + } + final String filename; + final String website; + if (uuid == null) { + uuid = UUID.randomUUID(); + website = Settings.WEB_URL + "upload.php?" + uuid; + filename = "plot." + extension; + } else { + website = Settings.WEB_URL + "save.php?" + uuid; + filename = file + "." + extension; + } + final URL url; + try { + url = new URL(Settings.WEB_URL + "?key=" + uuid + "&ip=" + Settings.WEB_IP + "&type=" + extension); + } catch (MalformedURLException e) { + e.printStackTrace(); + whenDone.run(); + return; + } + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + try { + final String boundary = Long.toHexString(System.currentTimeMillis()); + final URLConnection con = new URL(website).openConnection(); + con.setDoOutput(true); + con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); + try (OutputStream output = con.getOutputStream(); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8), true)) { + final String CRLF = "\r\n"; + writer.append("--" + boundary).append(CRLF); + writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF); + writer.append("Content-Type: text/plain; charset=" + StandardCharsets.UTF_8.displayName()).append(CRLF); + final String param = "value"; + writer.append(CRLF).append(param).append(CRLF).flush(); + writer.append("--" + boundary).append(CRLF); + writer.append("Content-Disposition: form-data; name=\"schematicFile\"; filename=\"" + filename + "\"").append(CRLF); + writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(filename)).append(CRLF); + writer.append("Content-Transfer-Encoding: binary").append(CRLF); + writer.append(CRLF).flush(); + writeTask.value = output; + writeTask.run(); + output.flush(); + writer.append(CRLF).flush(); + writer.append("--" + boundary + "--").append(CRLF).flush(); + } +// try (Reader response = new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)) { +// final char[] buffer = new char[256]; +// final StringBuilder result = new StringBuilder(); +// while (true) { +// final int r = response.read(buffer); +// if (r < 0) { +// break; +// } +// result.append(buffer, 0, r); +// } +// if (!result.toString().startsWith("Success")) { +// PS.debug(result); +// } +// } catch (IOException e) { +// e.printStackTrace(); +// } + final int responseCode = ((HttpURLConnection) con).getResponseCode(); + if (responseCode == 200) { + whenDone.value = url; + } + TaskManager.runTask(whenDone); + } catch (Exception e) { + e.printStackTrace(); + TaskManager.runTask(whenDone); + } + } + }); + } + /** * Resets the biome if it was modified * @param area diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java b/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java index 169772860..d92907c18 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java @@ -24,7 +24,6 @@ import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.schematic.PlotItem; - import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -34,14 +33,10 @@ 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.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -566,72 +561,26 @@ public abstract class SchematicHandler { return null; } - public URL upload(final CompoundTag tag, UUID uuid, String file) { + public void upload(final CompoundTag tag, UUID uuid, String file, RunnableVal whenDone) { if (tag == null) { PS.debug("&cCannot save empty tag"); - return null; + TaskManager.runTask(whenDone); + return; } - try { - String website; - if (uuid == null) { - uuid = UUID.randomUUID(); - website = Settings.WEB_URL + "upload.php?" + uuid; - file = "plot"; - } else { - website = Settings.WEB_URL + "save.php?" + uuid; + MainUtil.upload(uuid, file, "schematic", new RunnableVal() { + @Override + public void run(OutputStream output) { + try { + GZIPOutputStream gzip = new GZIPOutputStream(output, true); + NBTOutputStream nos = new NBTOutputStream(gzip); + nos.writeTag(tag); + nos.flush(); + gzip.flush(); + } catch (IOException e) { + e.printStackTrace(); + } } - final String boundary = Long.toHexString(System.currentTimeMillis()); - final URLConnection con = new URL(website).openConnection(); - con.setDoOutput(true); - con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); - try (OutputStream output = con.getOutputStream(); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8), true)) { - final String CRLF = "\r\n"; - writer.append("--" + boundary).append(CRLF); - writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF); - writer.append("Content-Type: text/plain; charset=" + StandardCharsets.UTF_8.displayName()).append(CRLF); - final String param = "value"; - writer.append(CRLF).append(param).append(CRLF).flush(); - writer.append("--" + boundary).append(CRLF); - writer.append("Content-Disposition: form-data; name=\"schematicFile\"; filename=\"" + file + ".schematic" + "\"").append(CRLF); - writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(file + ".schematic")).append(CRLF); - writer.append("Content-Transfer-Encoding: binary").append(CRLF); - writer.append(CRLF).flush(); - final GZIPOutputStream gzip = new GZIPOutputStream(output); - final NBTOutputStream nos = new NBTOutputStream(gzip); - nos.writeTag(tag); - gzip.finish(); - nos.flush(); - output.flush(); - writer.append(CRLF).flush(); - writer.append("--" + boundary + "--").append(CRLF).flush(); - nos.close(); - } -// try (Reader response = new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)) { -// final char[] buffer = new char[256]; -// final StringBuilder result = new StringBuilder(); -// while (true) { -// final int r = response.read(buffer); -// if (r < 0) { -// break; -// } -// result.append(buffer, 0, r); -// } -// if (!result.toString().equals("The file plot.schematic has been uploaded.")) { -// PS.debug(result); -// } -// } catch (IOException e) { -// e.printStackTrace(); -// } - final int responseCode = ((HttpURLConnection) con).getResponseCode(); - if (responseCode != 200) { - return null; - } - return new URL(Settings.WEB_URL + "?key=" + uuid + "&ip=" + Settings.WEB_IP); - } catch (IOException e) { - e.printStackTrace(); - } - return null; + }, whenDone); } /** diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/WorldUtil.java b/Core/src/main/java/com/intellectualcrafters/plot/util/WorldUtil.java index 75704efd6..77cf3db15 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/WorldUtil.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/WorldUtil.java @@ -1,9 +1,20 @@ package com.intellectualcrafters.plot.util; +import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.object.Location; +import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.RegionWrapper; +import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.schematic.PlotItem; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import java.util.UUID; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; public abstract class WorldUtil { public static WorldUtil IMP; @@ -19,6 +30,10 @@ public abstract class WorldUtil { public abstract String[] getSign(Location loc); public abstract Location getSpawn(String world); + + public abstract void setSpawn(Location loc); + + public abstract void saveWorld(String world); public abstract String getClosestMatchingName(PlotBlock plotBlock); @@ -37,4 +52,78 @@ public abstract class WorldUtil { public abstract void setSign(String world, int x, int y, int z, String[] lines); public abstract void setBiomes(String world, RegionWrapper region, String biome); + + public void upload(final Plot plot, final UUID uuid, final String file, final RunnableVal whenDone) { + if (plot == null) { + throw new IllegalArgumentException("Plot may not be null!"); + } + final Location home = plot.getHome(); + MainUtil.upload(uuid, file, "zip", new RunnableVal() { + @Override + public void run(OutputStream output) { + try (final ZipOutputStream zos = new ZipOutputStream(output)) { + final byte[] buffer = new byte[1024]; + final File dat = getDat(plot.getArea().worldname); + Location spawn = getSpawn(plot.getArea().worldname); + setSpawn(home); + if (dat != null) { + final ZipEntry ze = new ZipEntry("world" + File.separator + dat.getName()); + zos.putNextEntry(ze); + final FileInputStream in = new FileInputStream(dat); + int len; + while ((len = in.read(buffer)) > 0) { + zos.write(buffer, 0, len); + } + } + setSpawn(spawn); + for (Plot current : plot.getConnectedPlots()) { + final Location bot = current.getBottomAbs(); + final Location top = current.getTopAbs(); + final int brx = bot.getX() >> 9; + final int brz = bot.getZ() >> 9; + final int trx = top.getX() >> 9; + final int trz = top.getZ() >> 9; + for (int x = brx; x <= trx; x++) { + for (int z = brz; z <= trz; z++) { + final File file = getMcr(plot.getArea().worldname, x, z); + if (file != null) { + //final String name = "r." + (x - cx) + "." + (z - cz) + ".mca"; + String name = file.getName(); + final ZipEntry ze = new ZipEntry("world" + File.separator + "region" + File.separator + name); + zos.putNextEntry(ze); + final FileInputStream in = new FileInputStream(file); + int len; + while ((len = in.read(buffer)) > 0) { + zos.write(buffer, 0, len); + } + in.close(); + } + } + } + } + zos.closeEntry(); + zos.flush(); + zos.finish(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }, whenDone); + } + + public File getDat(final String world) { + final File file = new File(PS.get().IMP.getWorldContainer() + File.separator + world + File.separator + "level.dat"); + if (file.exists()) { + return file; + } + return null; + } + + public File getMcr(final String world, final int x, final int z) { + final File file = new File(PS.get().IMP.getWorldContainer(), world + File.separator + "region" + File.separator + "r." + x + "." + z + ".mca"); + if (file.exists()) { + return file; + } + return null; + } } diff --git a/Core/src/main/java/com/plotsquared/listener/WESubscriber.java b/Core/src/main/java/com/plotsquared/listener/WESubscriber.java index 0fb1817d7..8de7d2197 100644 --- a/Core/src/main/java/com/plotsquared/listener/WESubscriber.java +++ b/Core/src/main/java/com/plotsquared/listener/WESubscriber.java @@ -3,6 +3,7 @@ package com.plotsquared.listener; import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.util.MainUtil; @@ -14,13 +15,15 @@ import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.extent.EditSessionEvent; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extent.*; +import com.sk89q.worldedit.extent.AbstractDelegateExtent; +import com.sk89q.worldedit.extent.ChangeSetExtent; +import com.sk89q.worldedit.extent.MaskingExtent; import com.sk89q.worldedit.extent.reorder.MultiStageReorder; import com.sk89q.worldedit.extent.world.FastModeExtent; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.eventbus.EventHandler.Priority; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.world.World; - import java.lang.reflect.Field; import java.util.HashSet; @@ -39,18 +42,30 @@ public class WESubscriber { if (actor != null && actor.isPlayer()) { final String name = actor.getName(); final PlotPlayer pp = PlotPlayer.wrap(name); - if (pp != null && pp.getAttribute("worldedit")) { - return; - } - final HashSet mask = WEManager.getMask(pp); - if (mask.isEmpty()) { - if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) { - MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS); - } - if (PS.get().hasPlotArea(world)) { + final HashSet mask; + if (pp == null) { + Player player = (Player) actor; + Location loc = player.getLocation(); + com.intellectualcrafters.plot.object.Location pLoc = new com.intellectualcrafters.plot.object.Location(player.getWorld().getName(), loc.getBlockX(), loc.getBlockX(), loc.getBlockZ()); + Plot plot = pLoc.getPlot(); + if (plot == null) { event.setExtent(new com.sk89q.worldedit.extent.NullExtent()); + return; } + mask = plot.getRegions(); + } else if (pp.getAttribute("worldedit")) { return; + } else { + mask = WEManager.getMask(pp); + if (mask.isEmpty()) { + if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) { + MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS); + } + if (PS.get().hasPlotArea(world)) { + event.setExtent(new com.sk89q.worldedit.extent.NullExtent()); + } + return; + } } if (Settings.CHUNK_PROCESSOR) { if (Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT) { diff --git a/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java index e286ab099..b69b0adef 100644 --- a/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java +++ b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java @@ -19,6 +19,7 @@ import com.plotsquared.sponge.SpongeMain; import com.plotsquared.sponge.object.SpongePlayer; import net.minecraft.block.Block; import net.minecraft.world.biome.BiomeGenBase; +import org.apache.commons.lang3.NotImplementedException; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.block.BlockType; @@ -355,7 +356,20 @@ public class SpongeUtil extends WorldUtil { result.setY(getHighestBlock(world, result.getX(), result.getZ())); return result; } - + + @Override + public void setSpawn(Location loc) { + World world = getWorld(loc.getWorld()); + if (world != null) { + world.getProperties().setSpawnPosition(new Vector3i(loc.getX(), loc.getY(), loc.getZ())); + } + } + + @Override + public void saveWorld(String worldname) { + throw new NotImplementedException("TODO WIP"); // TODO FIXME + } + @Override public String[] getSign(final Location loc) { final World world = SpongeUtil.getWorld(loc.getWorld());