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)); + } + } + } + } +} diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 7aab7e8fd..18a28029f 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -817,6 +817,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; @@ -848,6 +849,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()); @@ -860,6 +865,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/bukkit/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java index 18864ccd8..60ef23a6b 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/CUIChannelListener.java @@ -40,11 +40,8 @@ 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); + session.describeCUI(plugin.wrapPlayer(player)); } } diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index 2a84f875c..7efb2b240 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -23,11 +23,13 @@ import com.sk89q.util.yaml.YAMLProcessor; import com.sk89q.wepif.PermissionsResolverManager; import com.sk89q.worldedit.*; 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.extension.platform.PlatformRejectionException; import com.sk89q.worldedit.extent.inventory.BlockBag; 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; @@ -389,6 +391,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/minecraft/util/commands/CommandsManager.java b/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java index b25c4429d..8d81f46cd 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); diff --git a/src/main/java/com/sk89q/worldedit/LocalSession.java b/src/main/java/com/sk89q/worldedit/LocalSession.java index 6470e50d3..5b07345b5 100644 --- a/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -625,10 +625,6 @@ public class LocalSession { } public void handleCUIInitializationMessage(String text) { - if (hasCUISupport()) { - return; - } - String[] split = text.split("\\|"); if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message setCUISupport(true); diff --git a/src/main/java/com/sk89q/worldedit/LocalWorld.java b/src/main/java/com/sk89q/worldedit/LocalWorld.java index e10b3f4f8..9dd3498cb 100644 --- a/src/main/java/com/sk89q/worldedit/LocalWorld.java +++ b/src/main/java/com/sk89q/worldedit/LocalWorld.java @@ -45,7 +45,8 @@ public abstract class LocalWorld extends AbstractWorld { 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; private KillFlags() { 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..c7dee7c79 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/bukkit/selections/CylinderSelection.java @@ -0,0 +1,80 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.bukkit.selections; + +import com.sk89q.worldedit.regions.selector.CylinderRegionSelector; +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.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/command/BrushCommands.java b/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index c0fa51e1b..0b0a62ae3 100644 --- a/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/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/command/SchematicCommands.java b/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index aaad773f9..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", @@ -234,7 +255,6 @@ 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 @@ -253,11 +273,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(); } } diff --git a/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 702c3d368..c8128d1eb 100644 --- a/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -346,7 +346,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" + @@ -356,6 +356,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, @@ -391,6 +392,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 diff --git a/src/main/java/com/sk89q/worldedit/math/geom/Polygons.java b/src/main/java/com/sk89q/worldedit/math/geom/Polygons.java new file mode 100644 index 000000000..c6f011243 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/math/geom/Polygons.java @@ -0,0 +1,64 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.math.geom; + +import com.sk89q.worldedit.BlockVector2D; +import com.sk89q.worldedit.Vector2D; + +import java.util.ArrayList; +import java.util.List; + +/** + * Helper method for anything related to polygons. + */ +public final class Polygons { + + private Polygons() { + + } + + /** + * 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; + } + +} diff --git a/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java b/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java index 73d1e0f44..e6eea8cff 100644 --- a/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java +++ b/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java @@ -20,11 +20,11 @@ package com.sk89q.worldedit.regions; import com.sk89q.worldedit.*; +import com.sk89q.worldedit.math.geom.Polygons; import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator; import com.sk89q.worldedit.regions.iterator.FlatRegionIterator; import com.sk89q.worldedit.world.World; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -375,22 +375,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 Polygons.polygonizeCylinder(center, radius, maxPoints); } } diff --git a/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java b/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java index e05bdab45..b048094f5 100644 --- a/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java +++ b/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java @@ -206,8 +206,6 @@ public class ConvexPolyhedralRegionSelector extends com.sk89q.worldedit.regions. 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) { @@ -234,8 +232,6 @@ public class ConvexPolyhedralRegionSelector extends com.sk89q.worldedit.regions. 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/selector/CylinderRegionSelector.java b/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java index ffd9c94b0..899a45d31 100644 --- a/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java +++ b/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java @@ -237,8 +237,6 @@ public class CylinderRegionSelector extends com.sk89q.worldedit.regions.Cylinder 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/schematic/MCEditSchematicFormat.java b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java index d205a8972..77f0c7036 100644 --- a/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java +++ b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java @@ -45,9 +45,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)); @@ -186,6 +184,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();