From 7c98cc0e010fdcc630c7e44b7f3a698297d47117 Mon Sep 17 00:00:00 2001 From: Trevor Wilson Date: Sun, 19 May 2013 02:32:06 -0500 Subject: [PATCH 01/12] Made CommandManager registration with parent public so hooks can be made to existing commands --- .../java/com/sk89q/minecraft/util/commands/CommandsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java b/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java index 1d6283d37..c8f0ffe2d 100644 --- a/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java +++ b/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java @@ -135,7 +135,7 @@ public abstract class CommandsManager { * @param parent * @return Commands Registered */ - private List registerMethods(Class cls, Method parent) { + public List registerMethods(Class cls, Method parent) { try { if (getInjector() == null) { return registerMethods(cls, parent, null); From ed123f4f648caa01725abc6d5e70f6af1ea2da3d Mon Sep 17 00:00:00 2001 From: Gimlao Date: Thu, 20 Jun 2013 20:04:28 +0300 Subject: [PATCH 02/12] [maze.js] Added Height, Size, Thickness and Flags --- contrib/craftscripts/maze.js | 367 +++++++++++++++++++++++++++++------ 1 file changed, 307 insertions(+), 60 deletions(-) diff --git a/contrib/craftscripts/maze.js b/contrib/craftscripts/maze.js index d76a9236e..dd5ca6a52 100644 --- a/contrib/craftscripts/maze.js +++ b/contrib/craftscripts/maze.js @@ -20,14 +20,76 @@ importPackage(Packages.com.sk89q.worldedit); importPackage(Packages.com.sk89q.worldedit.blocks); -context.checkArgs(1, -1, " [width] [length]"); +usage = " [width] [length] [height] [size] [thickness] flags\n"; +usage += "\n"; +usage += "Maze Flags:\n"; +usage += "• i adds an entry and an exit\n"; +usage += "• y places the entry and the exit randomly\n"; +usage += "• f adds a floor\n"; +usage += "• c adds a ceiling\n"; +usage += "• e places air blocks\n"; +usage += "• a places air blocks only\n"; +usage += "• v creates a vertical maze\n"; +usage += "\n"; +usage += "Solver Flags:\n"; +usage += "• s enables the maze solver\n"; +usage += "• g places glass if wrong or unvisited\n"; +usage += "• r places red wool if wrong\n"; +usage += "• b places blue wool if unvisited"; -var sess = context.remember(); +context.checkArgs(1, -1, usage); + +sess = context.remember(); +origin = player.getBlockIn(); // This may throw an exception that is caught by the script processor -var block = context.getBlock(argv[1]); -var w = argv.length > 2 ? parseInt(argv[2]) : 5; -var h = argv.length > 3 ? parseInt(argv[3]) : 5; +block = context.getBlock(argv[1]); + +if (argv.length > 7) flags = String(argv[7]); +else flags = false; + +if (argv.length > 6) { + if (parseInt(argv[6], 10)) wa = parseInt(argv[6], 10); + else flags = String(argv[6]), wa = 1; +} else wa = 1; + +if (argv.length > 5) { + if (parseInt(argv[5], 10)) s = parseInt(argv[5], 10); + else flags = String(argv[5]), s = 1, wa = 1; +} else s = 1; + +if (argv.length > 4) { + if (parseInt(argv[4], 10)) h = parseInt(argv[4], 10); + else flags = String(argv[4]), h = 2, s = 1, wa = 1; +} else h = 2; + +if (argv.length > 3) { + if (parseInt(argv[3], 10)) l = parseInt(argv[3], 10); + else flags = String(argv[3]), l = 5, h = 2, s = 1, wa = 1; +} else l = 5; + +if (argv.length > 2) { + if (parseInt(argv[2], 10)) w = parseInt(argv[2], 10); + else flags = String(argv[2]), w = 5, l = 5, h = 2, s = 1, wa = 1; +} else w = 5; + +if (flags) { + ee = flags.search("i") != -1 ? true : false; + r = flags.search("y") != -1 ? true : false; + if (r) ee = true; + f = flags.search("f") != -1 ? true : false; + c = flags.search("c") != -1 ? true : false; + e = flags.search("e") != -1 ? true : false; + ao = flags.search("a") != -1 ? true : false; + if (ao) f = c = false, e = true; + v = flags.search("v") != -1 ? true : false; + so = flags.search("s") != -1 ? true : false; + if (so) ee = true; + g = flags.search("g") != -1 ? true : false; + re = flags.search("r") != -1 ? true : false; + bl = flags.search("b") != -1 ? true : false; + if (g || re || bl) so = ee = true; +} else ee = r = f = c = e = ao = v = so = g = re = bl = false; function id(x, y) { return y * (w + 1) + x; @@ -42,91 +104,276 @@ function $y(i) { } function shuffle(arr) { - var i = arr.length; - if (i == 0) return false; + i = arr.length; + if (i === 0) return false; while (--i) { - var j = Math.floor(Math.random() * (i + 1)); - var tempi = arr[i]; - var tempj = arr[j]; + j = Math.floor(Math.random() * (i + 1)); + tempi = arr[i]; + tempj = arr[j]; arr[i] = tempj; arr[j] = tempi; } } -var stack = []; -var visited = {}; -var noWallLeft = new Array(w * h); -var noWallAbove = new Array(w * h); -var current = 0; +if (f || c) { + for (z = 1; z <= wa; z++) for (y = -wa; y <= l * (s + wa) - 1; y++) for (x = -wa; x <= w * (s + wa) - 1; x++) { + if (f) { + if (!v) sess.setBlock(origin.add(x, -z, y), block); + else sess.setBlock(origin.add(x, y, +z), block); + } -stack.push(id(0, 0)) + if (c) { + if (!v) sess.setBlock(origin.add(x, z - 1 + h, y), block); + else sess.setBlock(origin.add(x, y, -z + 1 - h), block); + } + } +} + +stack = []; +visited = []; +noWallLeft = []; +noWallAbove = []; + +stack.push(id(Math.floor(Math.random() * w), Math.floor(Math.random() * l))); while (stack.length > 0) { - var cell = stack.pop(); - var x = $x(cell), y = $y(cell); + cell = stack.pop(); + x = $x(cell); + y = $y(cell); visited[cell] = true; - - var neighbors = [] - + neighbors = []; + if (x > 0) neighbors.push(id(x - 1, y)); if (x < w - 1) neighbors.push(id(x + 1, y)); if (y > 0) neighbors.push(id(x, y - 1)); - if (y < h - 1) neighbors.push(id(x, y + 1)); - + if (y < l - 1) neighbors.push(id(x, y + 1)); + shuffle(neighbors); - + while (neighbors.length > 0) { - var neighbor = neighbors.pop(); - var nx = $x(neighbor), ny = $y(neighbor); - - if (visited[neighbor] != true) { + neighbor = neighbors.pop(); + nx = $x(neighbor); + ny = $y(neighbor); + + if (!visited[neighbor]) { stack.push(cell); - + if (y == ny) { - if (nx < x) { - noWallLeft[cell] = true; - } else { - noWallLeft[neighbor] = true; - } + if (nx < x) noWallLeft[cell] = true; + else noWallLeft[neighbor] = true; } else { - if (ny < y) { - noWallAbove[cell] = true; - } else { - noWallAbove[neighbor] = true; - } + if (ny < y) noWallAbove[cell] = true; + else noWallAbove[neighbor] = true; } - + stack.push(neighbor); break; } } } -/*for (var y = -1; y < h; y++) { - var line = ""; - for (var x = 0; x <= w; x++) { - var cell = id(x, y) - var l = y >= 0 ? (noWallLeft[cell] ? "_" : "|") : "_"; - var b = x < w ? (noWallAbove[id(x, y + 1)] ? " " : "_") : ""; - line += l + b; +if (!r) { + start = id(0, 0); + end = id(w - 1, l - 1); +} else { + start = id(0, Math.floor(Math.random() * l)); + end = id(w - 1, Math.floor(Math.random() * l)); +} + +if (ee) { + noWallLeft[start] = true; + noWallLeft[end + 1] = true; +} + +/*for (y = -1; y < l; y++) { + line = ""; + for (x = 0; x <= w; x++) { + cell = id(x, y); + a = y >= 0 ? (noWallLeft[cell] ? "_" : "|") : "_"; + b = x < w ? (noWallAbove[id(x, y + 1)] ? " " : "_") : ""; + line += a + b; } context.print(line); }*/ -var origin = player.getBlockIn(); +for (y = 0; y <= l; y++) for (x = 0; x <= w; x++) { + cell = id(x, y); -for (var y = 0; y <= h; y++) { - for (var x = 0; x <= w; x++) { - var cell = id(x, y) - if (!noWallLeft[cell] && y < h) { - sess.setBlock(origin.add(x * 2 - 1, 0, y * 2), block); - sess.setBlock(origin.add(x * 2 - 1, 1, y * 2), block); + if (!noWallLeft[cell] && cell != id(x, l)) { + if (!ao) { + for (z = 0; z < h; z++) for (yi = 0; yi < s; yi++) for (xi = 1; xi <= wa; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, z, y * (s + wa) + yi), block); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) + yi, -z), block); + } } - if (!noWallAbove[cell] && x < w) { - sess.setBlock(origin.add(x * 2, 0, y * 2 - 1), block); - sess.setBlock(origin.add(x * 2, 1, y * 2 - 1), block); + } else if (e && cell != id(x, l)) { + for (z = 0; z < h; z++) for (yi = 0; yi < s; yi++) for (xi = 1; xi <= wa; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, z, y * (s + wa) + yi), BaseBlock(0)); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) + yi, -z), BaseBlock(0)); } - sess.setBlock(origin.add(x * 2 - 1, 0, y * 2 - 1), block); - sess.setBlock(origin.add(x * 2 - 1, 1, y * 2 - 1), block); } -} \ No newline at end of file + + if (!noWallAbove[cell] && cell != id(w, y)) { + if (!ao) { + for (z = 0; z < h; z++) for (yi = 1; yi <= wa; yi++) for (xi = 0; xi < s; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, z, y * (s + wa) - yi), block); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) - yi, -z), block); + } + } + } else if (e && cell != id(w, y)) { + for (z = 0; z < h; z++) for (yi = 1; yi <= wa; yi++) for (xi = 0; xi < s; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, z, y * (s + wa) - yi), BaseBlock(0)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) - yi, -z), BaseBlock(0)); + } + } + + if (!ao) { + for (z = 0; z < h; z++) for (yi = 1; yi <= wa; yi++) for (xi = 1; xi <= wa; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, z, y * (s + wa) - yi), block); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) - yi, -z), block); + } + } + + if (e && cell != id(x, l) && cell != id(w, y)) { + for (z = 0; z < h; z++) for (yi = 0; yi < s; yi++) for (xi = 0; xi < s; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, z, y * (s + wa) + yi), BaseBlock(0)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) + yi, -z), BaseBlock(0)); + } + } +} + +if (so) { + stack = []; + visited = []; + wrong = []; + + stack.push(start); + + while (cell != end) { + if (visited[stack[stack.length - 1]]) wrong[cell] = true; + + cell = stack.pop(); + x = $x(cell); + y = $y(cell); + visited[cell] = true; + neighbors = []; + + if (noWallLeft[cell] && cell != start) neighbors.push(id(x - 1, y)); + if (noWallLeft[id(x + 1, y)]) neighbors.push(id(x + 1, y)); + if (noWallAbove[cell]) neighbors.push(id(x, y - 1)); + if (noWallAbove[id(x, y + 1)]) neighbors.push(id(x, y + 1)); + + shuffle(neighbors); + + while (neighbors.length > 0) { + neighbor = neighbors.pop(); + + if (!visited[neighbor]) { + stack.push(cell); + stack.push(neighbor); + break; + } + } + } + + for (y = 0; y <= l; y++) for (x = 0; x <= w; x++) { + cell = id(x, y); + + if (visited[cell] && !wrong[cell]) { + for (yi = 0; yi < s; yi++) for (xi = 0; xi < s; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, -1, y * (s + wa) + yi), BaseBlock(35, 5)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) + yi, +1), BaseBlock(35, 5)); + } + } + + if ((visited[cell] && !wrong[cell] && visited[id(x - 1, y)] && !wrong[id(x - 1, y)] && noWallLeft[cell]) || cell == start || id(x - 1, y) == end) { + for (xi = 1; xi <= wa; xi++) for (yi = 0; yi < s; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, -1, y * (s + wa) + yi), BaseBlock(35, 5)); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) + yi, +1), BaseBlock(35, 5)); + } + } + + if (visited[cell] && !wrong[cell] && visited[id(x, y - 1)] && !wrong[id(x, y - 1)] && noWallAbove[cell]) { + for (xi = 0; xi < s; xi++) for (yi = 1; yi <= wa; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, -1, y * (s + wa) - yi), BaseBlock(35, 5)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) - yi, +1), BaseBlock(35, 5)); + } + } + + if (g) { + if (visited[cell] && !wrong[cell] && (!visited[id(x - 1, y)] || wrong[id(x - 1, y)]) && noWallLeft[cell] && cell != start) { + for (z = 0; z < h; z++) for (xi = 1; xi <= wa; xi++) for (yi = 0; yi < s; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, z, y * (s + wa) + yi), BaseBlock(20)); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) + yi, -z), BaseBlock(20)); + } + } + + if ((!visited[cell] || wrong[cell]) && visited[id(x - 1, y)] && !wrong[id(x - 1, y)] && noWallLeft[cell] && id(x - 1, y) != end) { + for (z = 0; z < h; z++) for (xi = 1; xi <= wa; xi++) for (yi = 0; yi < s; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, z, y * (s + wa) + yi), BaseBlock(20)); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) + yi, -z), BaseBlock(20)); + } + } + + if (visited[cell] && !wrong[cell] && (!visited[id(x, y - 1)] || wrong[id(x, y - 1)]) && noWallAbove[cell]) { + for (z = 0; z < h; z++) for (xi = 0; xi < s; xi++) for (yi = 1; yi <= wa; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, z, y * (s + wa) - yi), BaseBlock(20)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) - yi, -z), BaseBlock(20)); + } + } + + if ((!visited[cell] || wrong[cell]) && visited[id(x, y - 1)] && !wrong[id(x, y - 1)] && noWallAbove[cell]) { + for (z = 0; z < h; z++) for (xi = 0; xi < s; xi++) for (yi = 1; yi <= wa; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, z, y * (s + wa) - yi), BaseBlock(20)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) - yi, -z), BaseBlock(20)); + } + } + } + + if (re) { + if (wrong[cell]) { + for (yi = 0; yi < s; yi++) for (xi = 0; xi < s; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, -1, y * (s + wa) + yi), BaseBlock(35, 14)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) + yi, +1), BaseBlock(35, 14)); + } + } + + if ((wrong[cell] || wrong[id(x - 1, y)]) && noWallLeft[cell]) { + for (xi = 1; xi <= wa; xi++) for (yi = 0; yi < s; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, -1, y * (s + wa) + yi), BaseBlock(35, 14)); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) + yi, +1), BaseBlock(35, 14)); + } + } + + if ((wrong[cell] || wrong[id(x, y - 1)]) && noWallAbove[cell]) { + for (xi = 0; xi < s; xi++) for (yi = 1; yi <= wa; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, -1, y * (s + wa) - yi), BaseBlock(35, 14)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) - yi, +1), BaseBlock(35, 14)); + } + } + } + + if (bl) { + if (!visited[cell] && y < l && x < w) { + for (yi = 0; yi < s; yi++) for (xi = 0; xi < s; xi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, -1, y * (s + wa) + yi), BaseBlock(35, 11)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) + yi, +1), BaseBlock(35, 11)); + } + } + + if ((!visited[cell] || !visited[id(x - 1, y)]) && noWallLeft[cell] && x > 0 && x < w) { + for (xi = 1; xi <= wa; xi++) for (yi = 0; yi < s; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) - xi, -1, y * (s + wa) + yi), BaseBlock(35, 11)); + else sess.setBlock(origin.add(x * (s + wa) - xi, y * (s + wa) + yi, +1), BaseBlock(35, 11)); + } + } + + if ((!visited[cell] || !visited[id(x, y - 1)]) && noWallAbove[cell]) { + for (xi = 0; xi < s; xi++) for (yi = 1; yi <= wa; yi++) { + if (!v) sess.setBlock(origin.add(x * (s + wa) + xi, -1, y * (s + wa) - yi), BaseBlock(35, 11)); + else sess.setBlock(origin.add(x * (s + wa) + xi, y * (s + wa) - yi, +1), BaseBlock(35, 11)); + } + } + } + } +} From 2a322afb2d6962d47d38d300f3e7c4e12081c8c0 Mon Sep 17 00:00:00 2001 From: James Fitzpatrick Date: Thu, 19 Dec 2013 16:32:31 +0000 Subject: [PATCH 03/12] Add support for listing schematics inside subdirectories --- .../worldedit/commands/SchematicCommands.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java b/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java index 8c5114273..643eb655d 100644 --- a/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java @@ -224,14 +224,12 @@ public class SchematicCommands { if (files == null) { throw new FilenameResolutionException(dir.getPath(), "Schematics directory invalid or not found."); } - StringBuilder build = new StringBuilder("Available schematics (Filename (Format)): "); final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0; // cleanup file list Arrays.sort(files, new Comparator(){ @Override public int compare(File f1, File f2) { - if (!f1.isFile() || !f2.isFile()) return -1; // don't care, will get removed // http://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified int result = sortType == 0 ? f1.getName().compareToIgnoreCase(f2.getName()) : // use name by default Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag @@ -240,14 +238,27 @@ public class SchematicCommands { } }); + player.print("Available schematics (Filename (Format)):"); + player.print(listFiles("", files)); + } + + private String listFiles(String prefix, File[] files) { + StringBuilder build = new StringBuilder(); for (File file : files) { + if (file.isDirectory()) { + build.append(listFiles(prefix + file.getName() + "/", file.listFiles())); + continue; + } + if (!file.isFile()) { continue; } + build.append("\n\u00a79"); SchematicFormat format = SchematicFormat.getFormat(file); - build.append(file.getName()).append(": ").append(format == null ? "Unknown" : format.getName()); + build.append(prefix).append(file.getName()) + .append(": ").append(format == null ? "Unknown" : format.getName()); } - player.print(build.toString()); + return build.toString(); } } From ae0b2df66e7458c6810e6acf59899c4ba7b321d0 Mon Sep 17 00:00:00 2001 From: ItsHarry Date: Sun, 5 Jan 2014 21:07:39 +0100 Subject: [PATCH 04/12] Allow use of InputStream, this allows schematics to be loaded e.g. as a resource. --- .../worldedit/schematic/MCEditSchematicFormat.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java index d654bed5d..8aa56edbb 100644 --- a/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java +++ b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -57,9 +58,7 @@ public class MCEditSchematicFormat extends SchematicFormat { super("MCEdit", "mcedit", "mce"); } - @Override - public CuboidClipboard load(File file) throws IOException, DataException { - FileInputStream stream = new FileInputStream(file); + public CuboidClipboard load(InputStream stream) throws IOException, DataException { NBTInputStream nbtStream = new NBTInputStream( new GZIPInputStream(stream)); @@ -194,6 +193,11 @@ public class MCEditSchematicFormat extends SchematicFormat { return clipboard; } + @Override + public CuboidClipboard load(File file) throws IOException, DataException { + return load(new FileInputStream(file)); + } + @Override public void save(CuboidClipboard clipboard, File file) throws IOException, DataException { int width = clipboard.getWidth(); From 359b8abfe38a049e2e7e2c0eccda1b2abbfd29f9 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 7 Jan 2014 01:44:28 +0100 Subject: [PATCH 05/12] ADD: CylinderSelection for worldguard to be able to create regions MOD: moved polygonize method of CylinderRegion to RegionUtil so it can be reused later on --- .../worldedit/bukkit/WorldEditPlugin.java | 4 ++ .../bukkit/selections/CylinderSelection.java | 61 +++++++++++++++++++ .../worldedit/regions/CylinderRegion.java | 20 +----- .../com/sk89q/worldedit/util/RegionUtil.java | 45 ++++++++++++++ 4 files changed, 113 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/sk89q/worldedit/bukkit/selections/CylinderSelection.java create mode 100644 src/main/java/com/sk89q/worldedit/util/RegionUtil.java diff --git a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index eaba0e2af..203cb351e 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -47,9 +47,11 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditOperation; import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.bukkit.selections.CuboidSelection; +import com.sk89q.worldedit.bukkit.selections.CylinderSelection; import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection; import com.sk89q.worldedit.bukkit.selections.Selection; import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Polygonal2DRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; @@ -397,6 +399,8 @@ public class WorldEditPlugin extends JavaPlugin { return new CuboidSelection(world, selector, (CuboidRegion) region); } else if (region instanceof Polygonal2DRegion) { return new Polygonal2DSelection(world, selector, (Polygonal2DRegion) region); + } else if (region instanceof CylinderRegion) { + return new CylinderSelection(world, selector, (CylinderRegion) region); } else { return null; } diff --git a/src/main/java/com/sk89q/worldedit/bukkit/selections/CylinderSelection.java b/src/main/java/com/sk89q/worldedit/bukkit/selections/CylinderSelection.java new file mode 100644 index 000000000..ac75f20b1 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/bukkit/selections/CylinderSelection.java @@ -0,0 +1,61 @@ +package com.sk89q.worldedit.bukkit.selections; + +import org.bukkit.World; + +import com.sk89q.worldedit.BlockVector2D; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.bukkit.BukkitUtil; +import com.sk89q.worldedit.regions.CylinderRegion; +import com.sk89q.worldedit.regions.CylinderRegionSelector; +import com.sk89q.worldedit.regions.RegionSelector; + +/** + * A selection representing a {@link CylinderRegion} + */ +public class CylinderSelection extends RegionSelection { + + private CylinderRegion cylRegion; + + public CylinderSelection(World world, RegionSelector selector, CylinderRegion region) { + super(world, selector, region); + this.cylRegion = region; + } + + public CylinderSelection(World world, BlockVector2D center, BlockVector2D radius, int minY, int maxY) { + super(world); + LocalWorld lWorld = BukkitUtil.getLocalWorld(world); + + // Validate input + minY = Math.min(Math.max(0, minY), world.getMaxHeight()); + maxY = Math.min(Math.max(0, maxY), world.getMaxHeight()); + + // Create and set up new selector + CylinderRegionSelector sel = new CylinderRegionSelector(lWorld, center, radius, minY, maxY); + + // set up selection + cylRegion = sel.getIncompleteRegion(); + + // set up RegionSelection + setRegionSelector(sel); + setRegion(cylRegion); + } + + /** + * Returns the center vector of the cylinder + * + * @return the center + */ + public BlockVector2D getCenter() { + return cylRegion.getCenter().toVector2D().toBlockVector2D(); + } + + /** + * Returns the radius vector of the cylinder + * + * @return the radius + */ + public BlockVector2D getRadius() { + return cylRegion.getRadius().toBlockVector2D(); + } + +} diff --git a/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java b/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java index 998c998db..b2fa41c32 100644 --- a/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java +++ b/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java @@ -22,11 +22,13 @@ package com.sk89q.worldedit.regions; import java.util.ArrayList; import java.util.Iterator; import java.util.List; + import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.util.RegionUtil; /** * Represents a cylindrical region. @@ -366,22 +368,6 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { @Override public List polygonize(int maxPoints) { - final Vector2D radius = getRadius(); - int nPoints = (int) Math.ceil(Math.PI*radius.length()); - - // These strange semantics for maxPoints are copied from the selectSecondary method. - if (maxPoints >= 0 && nPoints >= maxPoints) { - nPoints = maxPoints - 1; - } - - final List points = new ArrayList(nPoints); - for (int i = 0; i < nPoints; ++i) { - double angle = i * (2.0 * Math.PI) / nPoints; - final Vector2D pos = new Vector2D(Math.cos(angle), Math.sin(angle)); - final BlockVector2D blockVector2D = pos.multiply(radius).add(center).toBlockVector2D(); - points.add(blockVector2D); - } - - return points; + return RegionUtil.polygonizeCylinder(center, radius, maxPoints); } } diff --git a/src/main/java/com/sk89q/worldedit/util/RegionUtil.java b/src/main/java/com/sk89q/worldedit/util/RegionUtil.java new file mode 100644 index 000000000..44eae2aa2 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/util/RegionUtil.java @@ -0,0 +1,45 @@ +package com.sk89q.worldedit.util; + +import java.util.ArrayList; +import java.util.List; + +import com.sk89q.worldedit.BlockVector2D; +import com.sk89q.worldedit.Vector2D; + +/** + * Helper method for anything related to region calculations. + */ +public class RegionUtil { + + private RegionUtil() { + + } + + /** + * Calculates the polygon shape of a cylinder which can then be used for e.g. intersection detection. + * + * @param center the center point of the cylinder + * @param radius the radius of the cylinder + * @param maxPoints max points to be used for the calculation + * @return a list of {@link BlockVector2D} which resemble the shape as a polygon + */ + public static List polygonizeCylinder(Vector2D center, Vector2D radius, int maxPoints) { + int nPoints = (int) Math.ceil(Math.PI*radius.length()); + + // These strange semantics for maxPoints are copied from the selectSecondary method. + if (maxPoints >= 0 && nPoints >= maxPoints) { + nPoints = maxPoints - 1; + } + + final List points = new ArrayList(nPoints); + for (int i = 0; i < nPoints; ++i) { + double angle = i * (2.0 * Math.PI) / nPoints; + final Vector2D pos = new Vector2D(Math.cos(angle), Math.sin(angle)); + final BlockVector2D blockVector2D = pos.multiply(radius).add(center).toBlockVector2D(); + points.add(blockVector2D); + } + + return points; + } + +} From e70c82c7c0609a5a95869c18b37b1c41e4480837 Mon Sep 17 00:00:00 2001 From: ReneZeidler Date: Sat, 1 Feb 2014 07:23:01 -0800 Subject: [PATCH 06/12] Don't send SelectionShapeEvent events in the describeCUI/describeLegacyCUI methods, that event is already sent in dispatchCUISelection in LocalSession --- .../worldedit/regions/ConvexPolyhedralRegionSelector.java | 6 +----- .../com/sk89q/worldedit/regions/CylinderRegionSelector.java | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java b/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java index ba4d941ea..6131c7435 100644 --- a/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java +++ b/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java @@ -183,9 +183,7 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion public void describeCUI(LocalSession session, LocalPlayer player) { Collection vertices = region.getVertices(); Collection triangles = region.getTriangles(); - - player.dispatchCUIEvent(new SelectionShapeEvent(getTypeID())); - + Map vertexIds = new HashMap(vertices.size()); int lastVertexId = -1; for (Vector vertex : vertices) { @@ -212,8 +210,6 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion if (isDefined()) { session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getArea())); - } else { - session.dispatchCUIEvent(player, new SelectionShapeEvent(getLegacyTypeID())); } } } diff --git a/src/main/java/com/sk89q/worldedit/regions/CylinderRegionSelector.java b/src/main/java/com/sk89q/worldedit/regions/CylinderRegionSelector.java index 54585f708..f33937240 100644 --- a/src/main/java/com/sk89q/worldedit/regions/CylinderRegionSelector.java +++ b/src/main/java/com/sk89q/worldedit/regions/CylinderRegionSelector.java @@ -199,8 +199,6 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion { if (isDefined()) { session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getArea())); - } else { - session.dispatchCUIEvent(player, new SelectionShapeEvent(getLegacyTypeID())); } } From 747de4cab7b98170c9e613767c80a786d097b091 Mon Sep 17 00:00:00 2001 From: ReneZeidler Date: Sat, 1 Feb 2014 07:24:29 -0800 Subject: [PATCH 07/12] That check is also done in the LocalSession, let the LocalSession decide what to do with multiple packets. --- .../java/com/sk89q/worldedit/bukkit/CUIChannelListener.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java b/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java index e846e6d1c..f3cd85bf8 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java @@ -39,10 +39,6 @@ public class CUIChannelListener implements PluginMessageListener { @Override public void onPluginMessageReceived(String channel, Player player, byte[] message) { LocalSession session = plugin.getSession(player); - if (session.hasCUISupport()) { // Already initialized - return; - } - String text = new String(message, UTF_8_CHARSET); session.handleCUIInitializationMessage(text); } From e25e1bfe67aa747d2a8954757bd5ffb080aff72d Mon Sep 17 00:00:00 2001 From: ReneZeidler Date: Sat, 1 Feb 2014 08:21:59 -0800 Subject: [PATCH 08/12] Let the handshake packet refresh the CUI protocol version (it happens that players join with another client before the previous session expires) and also send the current selection when receiving a handshake packet (for when the player joins and the previous session did not expire) --- src/main/java/com/sk89q/worldedit/LocalSession.java | 9 ++++----- .../com/sk89q/worldedit/bukkit/CUIChannelListener.java | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/LocalSession.java b/src/main/java/com/sk89q/worldedit/LocalSession.java index 7e73d222d..72b744d8c 100644 --- a/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -605,13 +605,12 @@ public class LocalSession { } public void handleCUIInitializationMessage(String text) { - if (hasCUISupport()) { - return; - } - + if(!hasCUISupport()) { + setCUISupport(true); + } + String[] split = text.split("\\|"); if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message - setCUISupport(true); try { setCUIVersion(Integer.parseInt(split[1])); } catch (NumberFormatException e) { diff --git a/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java b/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java index f3cd85bf8..03d9014a7 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java @@ -41,5 +41,6 @@ public class CUIChannelListener implements PluginMessageListener { LocalSession session = plugin.getSession(player); String text = new String(message, UTF_8_CHARSET); session.handleCUIInitializationMessage(text); + session.describeCUI(plugin.wrapPlayer(player)); } } From c47f50696dfa70837641528ad54dd851ab165852 Mon Sep 17 00:00:00 2001 From: ReneZeidler Date: Sat, 1 Feb 2014 08:25:43 -0800 Subject: [PATCH 09/12] Fix indentation --- src/main/java/com/sk89q/worldedit/LocalSession.java | 8 ++++---- .../worldedit/regions/ConvexPolyhedralRegionSelector.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/LocalSession.java b/src/main/java/com/sk89q/worldedit/LocalSession.java index 72b744d8c..15b2c3153 100644 --- a/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -605,10 +605,10 @@ public class LocalSession { } public void handleCUIInitializationMessage(String text) { - if(!hasCUISupport()) { - setCUISupport(true); - } - + if(!hasCUISupport()) { + setCUISupport(true); + } + String[] split = text.split("\\|"); if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message try { diff --git a/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java b/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java index 6131c7435..6dfab10b2 100644 --- a/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java +++ b/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSelector.java @@ -183,7 +183,7 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion public void describeCUI(LocalSession session, LocalPlayer player) { Collection vertices = region.getVertices(); Collection triangles = region.getTriangles(); - + Map vertexIds = new HashMap(vertices.size()); int lastVertexId = -1; for (Vector vertex : vertices) { From be8bb784f8675ac0804b2668f387dbb6eb011197 Mon Sep 17 00:00:00 2001 From: ReneZeidler Date: Sat, 1 Feb 2014 08:30:40 -0800 Subject: [PATCH 10/12] Only enable CUI support when the message is valid. Also the check if support isn't already enabled is not really needed, as it will just overwrite the field with the same value. --- src/main/java/com/sk89q/worldedit/LocalSession.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/LocalSession.java b/src/main/java/com/sk89q/worldedit/LocalSession.java index 15b2c3153..4c0ff68d1 100644 --- a/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -605,12 +605,9 @@ public class LocalSession { } public void handleCUIInitializationMessage(String text) { - if(!hasCUISupport()) { - setCUISupport(true); - } - String[] split = text.split("\\|"); if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message + setCUISupport(true); try { setCUIVersion(Integer.parseInt(split[1])); } catch (NumberFormatException e) { From 8868aa94d3f04b1ef8ce765535c3422a89a02684 Mon Sep 17 00:00:00 2001 From: TomyLobo Date: Sun, 23 Mar 2014 19:40:03 +0100 Subject: [PATCH 11/12] The /butcher command no longer kills mobs with a name tag. This behaviour can be overridden with the new -t flag. The -f flag encompasses this flag. --- src/main/java/com/sk89q/worldedit/LocalWorld.java | 3 ++- .../java/com/sk89q/worldedit/bukkit/BukkitWorld.java | 9 +++++++++ .../java/com/sk89q/worldedit/commands/BrushCommands.java | 1 + .../com/sk89q/worldedit/commands/UtilityCommands.java | 4 +++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/LocalWorld.java b/src/main/java/com/sk89q/worldedit/LocalWorld.java index 449faa681..939286e9c 100644 --- a/src/main/java/com/sk89q/worldedit/LocalWorld.java +++ b/src/main/java/com/sk89q/worldedit/LocalWorld.java @@ -53,7 +53,8 @@ public abstract class LocalWorld implements World { public static final int ANIMALS = 1 << 2; public static final int GOLEMS = 1 << 3; public static final int AMBIENT = 1 << 4; - public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT; + public static final int TAGGED = 1 << 5; + public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT | TAGGED; public static final int WITH_LIGHTNING = 1 << 20; } diff --git a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index c7bf76097..9046a5759 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -936,6 +936,7 @@ public class BukkitWorld extends LocalWorld { boolean withLightning = (flags & KillFlags.WITH_LIGHTNING) != 0; boolean killGolems = (flags & KillFlags.GOLEMS) != 0; boolean killAmbient = (flags & KillFlags.AMBIENT) != 0; + boolean killTagged = (flags & KillFlags.TAGGED) != 0; int num = 0; double radiusSq = radius * radius; @@ -967,6 +968,10 @@ public class BukkitWorld extends LocalWorld { continue; } + if (!killTagged && isTagged(ent)) { + continue; + } + if (radius < 0 || bukkitOrigin.distanceSquared(ent.getLocation()) <= radiusSq) { if (withLightning) { world.strikeLightningEffect(ent.getLocation()); @@ -979,6 +984,10 @@ public class BukkitWorld extends LocalWorld { return num; } + private static boolean isTagged(LivingEntity ent) { + return ent.getCustomName() != null; + } + /** * Remove entities in an area. * diff --git a/src/main/java/com/sk89q/worldedit/commands/BrushCommands.java b/src/main/java/com/sk89q/worldedit/commands/BrushCommands.java index cffe67220..e49e0fd39 100644 --- a/src/main/java/com/sk89q/worldedit/commands/BrushCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/BrushCommands.java @@ -281,6 +281,7 @@ public class BrushCommands { flags.or(KillFlags.GOLEMS , flagString.contains("g"), "worldedit.butcher.golems"); flags.or(KillFlags.ANIMALS , flagString.contains("a"), "worldedit.butcher.animals"); flags.or(KillFlags.AMBIENT , flagString.contains("b"), "worldedit.butcher.ambient"); + flags.or(KillFlags.TAGGED , flagString.contains("t"), "worldedit.butcher.tagged"); flags.or(KillFlags.WITH_LIGHTNING, flagString.contains("l"), "worldedit.butcher.lightning"); } BrushTool tool = session.getBrushTool(player.getItemInHand()); diff --git a/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java b/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java index 12b88fbf6..162014788 100644 --- a/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java @@ -345,7 +345,7 @@ public class UtilityCommands { @Command( aliases = { "butcher" }, usage = "[radius]", - flags = "plangbf", + flags = "plangbtf", desc = "Kill all or nearby mobs", help = "Kills nearby mobs, based on radius, if none is given uses default in configuration.\n" + @@ -355,6 +355,7 @@ public class UtilityCommands { " -g also kills Golems.\n" + " -a also kills animals.\n" + " -b also kills ambient mobs.\n" + + " -t also kills mobs with name tags.\n" + " -f compounds all previous flags.\n" + " -l strikes lightning on each killed mob.", min = 0, @@ -390,6 +391,7 @@ public class UtilityCommands { flags.or(KillFlags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems"); flags.or(KillFlags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals"); flags.or(KillFlags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient"); + flags.or(KillFlags.TAGGED , args.hasFlag('t'), "worldedit.butcher.tagged"); flags.or(KillFlags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning"); // If you add flags here, please add them to com.sk89q.worldedit.commands.BrushCommands.butcherBrush() as well From c8246ec9620ccc9865b04b52840ef5690dd45656 Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 1 May 2014 18:00:59 -0700 Subject: [PATCH 12/12] Merge pull request #239 --- .../worldedit/command/SchematicCommands.java | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index c901924db..90afb104d 100644 --- a/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -19,27 +19,17 @@ package com.sk89q.worldedit.command; +import com.sk89q.minecraft.util.commands.*; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.schematic.SchematicFormat; +import com.sk89q.worldedit.world.DataException; + import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.Arrays; import java.util.Comparator; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Console; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.FilenameResolutionException; -import com.sk89q.worldedit.LocalConfiguration; -import com.sk89q.worldedit.LocalPlayer; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.world.DataException; -import com.sk89q.worldedit.schematic.SchematicFormat; - /** * Commands related to schematics * @@ -181,6 +171,37 @@ public class SchematicCommands { } } + @Command( + aliases = { "delete", "d" }, + usage = "", + desc = "Delete a schematic from the schematic list", + help = "Delete a schematic from the schematic list", + min = 1, + max = 1 + ) + @CommandPermissions("worldedit.schematic.delete") + public void delete(CommandContext args, LocalSession session, LocalPlayer player, + EditSession editSession) throws WorldEditException { + + LocalConfiguration config = we.getConfiguration(); + String filename = args.getString(0); + + File dir = we.getWorkingDirectoryFile(config.saveDir); + File f = we.getSafeSaveFile(player, dir, filename, "schematic", "schematic"); + + if (!f.exists()) { + player.printError("Schematic " + filename + " does not exist!"); + return; + } + + if (!f.delete()) { + player.printError("Deletion of " + filename + " failed! Maybe it is read-only."); + return; + } + + player.print(filename + " has been deleted."); + } + @Command( aliases = {"formats", "listformats", "f"}, desc = "List available schematic formats",