From e8af1384d3c746b50380228a848c7062d3b6eb9d Mon Sep 17 00:00:00 2001 From: sk89q Date: Tue, 4 Jan 2011 14:35:36 -0800 Subject: [PATCH 01/13] Fixed WorldEdit bridge. --- src/WorldEdit.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/WorldEdit.java b/src/WorldEdit.java index 1b202847c..24b9be82e 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -94,7 +94,7 @@ public class WorldEdit extends Plugin { } /** - * Get the CraftBook version. + * Get the WorldEdit version. * * @return */ @@ -121,4 +121,13 @@ public class WorldEdit extends Plugin { return version; } + + /** + * Returns the listener for the WorldEdit bridge. + * + * @return + */ + public HMWorldEditListener getListener() { + return listener; + } } From b8426317d9c391fcc9c926c4dea4717082759d4d Mon Sep 17 00:00:00 2001 From: sk89q Date: Tue, 4 Jan 2011 14:41:15 -0800 Subject: [PATCH 02/13] Fixed permissions checking being completely erroneous. --- src/com/sk89q/worldedit/WorldEditController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/sk89q/worldedit/WorldEditController.java b/src/com/sk89q/worldedit/WorldEditController.java index 95a1f3d32..e874ea1b6 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -1850,7 +1850,7 @@ public class WorldEditController { split[0] = split[0].substring(1); } - if (canUseCommand(player, split[0])) { + if (canUseCommand(player, split[0].substring(1))) { LocalSession session = getSession(player); BlockBag blockBag = session.getBlockBag(player); From fea4be016197b61134af039ff4e2524029161ffe Mon Sep 17 00:00:00 2001 From: sk89q Date: Tue, 4 Jan 2011 14:42:44 -0800 Subject: [PATCH 03/13] Further fixed permissions. --- .../sk89q/worldedit/WorldEditController.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/com/sk89q/worldedit/WorldEditController.java b/src/com/sk89q/worldedit/WorldEditController.java index e874ea1b6..d08902ac5 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -643,7 +643,7 @@ public class WorldEditController { // Single super pickaxe mode } else if (split[0].equalsIgnoreCase("/single")) { - if (!canUseCommand(player, "//")) { + if (!canUseCommand(player, "/")) { player.printError("You don't have permission for super pickaxe usage."); return true; } @@ -658,7 +658,7 @@ public class WorldEditController { } else if (split[0].equalsIgnoreCase("/area") || split[0].equalsIgnoreCase("/recur")) { - if (!canUseCommand(player, "//")) { + if (!canUseCommand(player, "/")) { player.printError("You don't have permission for super pickaxe usage."); return true; } @@ -1733,7 +1733,7 @@ public class WorldEditController { * @param player */ public void handleArmSwing(LocalPlayer player) { - if (!canUseCommand(player, "//")) + if (!canUseCommand(player, "/")) return; } @@ -1751,12 +1751,12 @@ public class WorldEditController { // This prevents needless sessions from being created if (!hasSession(player) && !(itemInHand == config.wandItem && - canUseCommand(player, "//pos2"))) { return false; } + canUseCommand(player, "/pos2"))) { return false; } LocalSession session = getSession(player); if (itemInHand == config.wandItem && session.isToolControlEnabled() - && canUseCommand(player, "//pos2")) { + && canUseCommand(player, "/pos2")) { session.setPos2(clicked); try { player.print("Second position set to " + clicked @@ -1785,8 +1785,8 @@ public class WorldEditController { public boolean handleBlockLeftClick(LocalPlayer player, LocalWorld world, Vector clicked) { - if (!canUseCommand(player, "//pos1") - && !canUseCommand(player, "//")) { return false; } + if (!canUseCommand(player, "/pos1") + && !canUseCommand(player, "/")) { return false; } LocalSession session = getSession(player); @@ -1961,10 +1961,10 @@ public class WorldEditController { */ private boolean canUseCommand(LocalPlayer player, String command) { // Allow the /worldeditselect permission - if (command.equalsIgnoreCase("//pos1") - || command.equalsIgnoreCase("//pos2") - || command.equalsIgnoreCase("//hpos1") - || command.equalsIgnoreCase("//hpos2")) { + if (command.equalsIgnoreCase("/pos1") + || command.equalsIgnoreCase("/pos2") + || command.equalsIgnoreCase("/hpos1") + || command.equalsIgnoreCase("/hpos2")) { return player.hasPermission(command) || player.hasPermission("worldeditselect") || player.hasPermission("worldedit"); From e8d6c0acfe8bb310ad0e188d1a1f14115153e936 Mon Sep 17 00:00:00 2001 From: sk89q Date: Tue, 4 Jan 2011 14:43:28 -0800 Subject: [PATCH 04/13] Updated CHANGELOG for 2.5.1. --- CHANGELOG.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2e1949fe4..362d9f9de 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,8 @@ +2.5.1: +- Fixed the WorldEdit bridge used by CraftBook and other plugins. +- Fixed issues with permissions where the only reliable permission was + /worldedit. + 2.5: - Fixed issues with permissions not being read correctly. - WorldEdit is now world-aware (not that the Minecraft server is). From 2f71a32f64af34f8c2ab99d3ea1b4fe70718540d Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 10:52:48 -0800 Subject: [PATCH 05/13] Fixed inaccuracy with LocalPlayer.getBlockIn() and LocalPlayer.getBlockOn(). --- src/com/sk89q/worldedit/LocalPlayer.java | 7 +++++-- src/com/sk89q/worldedit/WorldVector.java | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/com/sk89q/worldedit/LocalPlayer.java b/src/com/sk89q/worldedit/LocalPlayer.java index 621cad592..d776c43a4 100644 --- a/src/com/sk89q/worldedit/LocalPlayer.java +++ b/src/com/sk89q/worldedit/LocalPlayer.java @@ -276,7 +276,9 @@ public abstract class LocalPlayer { * @return point */ public WorldVector getBlockIn() { - return getPosition(); + WorldVector pos = getPosition(); + return WorldVector.toBlockPoint(pos.getWorld(), pos.getX(), + pos.getY(), pos.getZ()); } /** @@ -286,7 +288,8 @@ public abstract class LocalPlayer { */ public WorldVector getBlockOn() { WorldVector pos = getPosition(); - return new WorldVector(pos.getWorld(), pos.subtract(0, 1, 0)); + return WorldVector.toBlockPoint(pos.getWorld(), pos.getX(), + pos.getY() - 1, pos.getZ()); } /** diff --git a/src/com/sk89q/worldedit/WorldVector.java b/src/com/sk89q/worldedit/WorldVector.java index 469cba030..63130441a 100644 --- a/src/com/sk89q/worldedit/WorldVector.java +++ b/src/com/sk89q/worldedit/WorldVector.java @@ -93,6 +93,21 @@ public class WorldVector extends Vector { return world; } + /** + * Get a block point from a point. + * + * @param x + * @param y + * @param z + * @return point + */ + public static WorldVector toBlockPoint(LocalWorld world, double x, double y, + double z) { + return new WorldVector(world, (int)Math.floor(x), + (int)Math.floor(y), + (int)Math.floor(z)); + } + /** * Gets a BlockVector version. * From da4480ab49cb72f488f521427164d235856b28c4 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 10:59:06 -0800 Subject: [PATCH 06/13] Did some minor Vector optimization. --- src/com/sk89q/worldedit/EditSession.java | 3 ++- src/com/sk89q/worldedit/Vector.java | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/com/sk89q/worldedit/EditSession.java b/src/com/sk89q/worldedit/EditSession.java index 3c8e1d0c4..1d2f4c6a0 100755 --- a/src/com/sk89q/worldedit/EditSession.java +++ b/src/com/sk89q/worldedit/EditSession.java @@ -1579,6 +1579,7 @@ public class EditSession { public int simulateSnow(Vector pos, int radius) throws MaxChangedBlocksException { int affected = 0; + int radiusSq = (int)Math.pow(radius, 2); int ox = pos.getBlockX(); int oy = pos.getBlockY(); @@ -1589,7 +1590,7 @@ public class EditSession { for (int x = ox - radius; x <= ox + radius; x++) { for (int z = oz - radius; z <= oz + radius; z++) { - if ((new Vector(x, oy, z)).distance(pos) > radius) { + if ((new Vector(x, oy, z)).distanceSq(pos) > radiusSq) { continue; } diff --git a/src/com/sk89q/worldedit/Vector.java b/src/com/sk89q/worldedit/Vector.java index a499e4d07..055d02509 100644 --- a/src/com/sk89q/worldedit/Vector.java +++ b/src/com/sk89q/worldedit/Vector.java @@ -446,6 +446,18 @@ public class Vector { Math.pow(pt.z - z, 2)); } + /** + * Get the distance away from a point, squared. + * + * @param pt + * @return distance + */ + public double distanceSq(Vector pt) { + return Math.pow(pt.x - x, 2) + + Math.pow(pt.y - y, 2) + + Math.pow(pt.z - z, 2); + } + /** * Checks to see if a vector is contained with another. * From b26624bc9b5ed7cabc1f4e3d0ba568822151832a Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 11:26:27 -0800 Subject: [PATCH 07/13] Moved most methods of ServerInterface to LocalWorld. --- src/HMPlayer.java | 15 +- src/HMServerInterface.java | 388 +--------------- src/HMWorld.java | 419 ++++++++++++++++++ src/HMWorldEditListener.java | 21 +- src/com/sk89q/worldedit/EditSession.java | 49 +- src/com/sk89q/worldedit/LocalPlayer.java | 21 +- src/com/sk89q/worldedit/LocalWorld.java | 151 +++++++ src/com/sk89q/worldedit/ServerInterface.java | 160 +------ .../sk89q/worldedit/WorldEditController.java | 17 +- .../worldedit/superpickaxe/AreaPickaxe.java | 10 +- .../worldedit/superpickaxe/BlockReplacer.java | 4 +- .../worldedit/superpickaxe/QueryTool.java | 5 +- .../superpickaxe/RecursivePickaxe.java | 9 +- .../worldedit/superpickaxe/SinglePickaxe.java | 12 +- .../superpickaxe/SuperPickaxeMode.java | 3 +- .../worldedit/superpickaxe/TreePlanter.java | 7 +- 16 files changed, 666 insertions(+), 625 deletions(-) create mode 100644 src/HMWorld.java diff --git a/src/HMPlayer.java b/src/HMPlayer.java index 4c3df8dce..a7dcbfd03 100644 --- a/src/HMPlayer.java +++ b/src/HMPlayer.java @@ -34,15 +34,20 @@ public class HMPlayer extends LocalPlayer { * Stores the player. */ private Player player; + /** + * World. + */ + private HMWorld world; /** * Construct the object. * * @param player */ - public HMPlayer(ServerInterface server, Player player) { + public HMPlayer(ServerInterface server, HMWorld world, Player player) { super(server); this.player = player; + this.world = world; } /** @@ -123,7 +128,7 @@ public class HMPlayer extends LocalPlayer { * @return point */ public WorldVector getPosition() { - return new WorldVector(null, player.getX(), player.getY(), player.getZ()); + return new WorldVector(world, player.getX(), player.getY(), player.getZ()); } /** @@ -132,7 +137,7 @@ public class HMPlayer extends LocalPlayer { * @return point */ public LocalWorld getWorld() { - return null; + return world; } /** @@ -163,7 +168,7 @@ public class HMPlayer extends LocalPlayer { public boolean passThroughForwardWall(int range) { boolean foundNext = false; int searchDist = 0; - HitBlox hitBlox = new HitBlox(player,range, 0.2); + HitBlox hitBlox = new HitBlox(player, range, 0.2); LocalWorld world = getPosition().getWorld(); Block block; while ((block = hitBlox.getNextBlock()) != null) { @@ -174,7 +179,7 @@ public class HMPlayer extends LocalPlayer { if (block.getType() == 0) { if (foundNext) { Vector v = new Vector(block.getX(), block.getY() - 1, block.getZ()); - if (server.getBlockType(world, v) == 0) { + if (world.getBlockType(v) == 0) { setPosition(v.add(0.5, 0, 0.5)); return true; } diff --git a/src/HMServerInterface.java b/src/HMServerInterface.java index c10ded3d7..d2fd5a7ad 100644 --- a/src/HMServerInterface.java +++ b/src/HMServerInterface.java @@ -18,380 +18,12 @@ */ import com.sk89q.worldedit.*; -import com.sk89q.worldedit.blocks.BaseItemStack; -import java.util.logging.Logger; -import java.util.Random; /** * * @author sk89q */ public class HMServerInterface extends ServerInterface { - /** - * Logger. - */ - private final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); - /** - * Random generator. - */ - private Random random = new Random(); - - /** - * Set block type. - * - * @param pt - * @param type - * @return - */ - public boolean setBlockType(LocalWorld world, Vector pt, int type) { - // Can't set colored cloth or crash - if ((type >= 21 && type <= 34) || type == 36) { - return false; - } - return etc.getServer().setBlockAt(type, pt.getBlockX(), pt.getBlockY(), - pt.getBlockZ()); - } - - /** - * Get block type. - * - * @param pt - * @return - */ - public int getBlockType(LocalWorld world, Vector pt) { - return etc.getServer().getBlockIdAt(pt.getBlockX(), pt.getBlockY(), - pt.getBlockZ()); - } - - /** - * Set block data. - * - * @param pt - * @param data - * @return - */ - public void setBlockData(LocalWorld world, Vector pt, int data) { - etc.getServer().setBlockData(pt.getBlockX(), pt.getBlockY(), - pt.getBlockZ(), data); - } - - /** - * Get block data. - * - * @param pt - * @return - */ - public int getBlockData(LocalWorld world, Vector pt) { - return etc.getServer().getBlockData(pt.getBlockX(), pt.getBlockY(), - pt.getBlockZ()); - } - - /** - * Set sign text. - * - * @param pt - * @param text - */ - public void setSignText(LocalWorld world, Vector pt, String[] text) { - Sign signData = (Sign)etc.getServer().getComplexBlock( - pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (signData == null) { - return; - } - for (byte i = 0; i < 4; i++) { - signData.setText(i, text[i]); - } - signData.update(); - } - - /** - * Get sign text. - * - * @param pt - * @return - */ - public String[] getSignText(LocalWorld world, Vector pt) { - Sign signData = (Sign)etc.getServer().getComplexBlock( - pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (signData == null) { - return new String[]{"", "", "", ""}; - } - String[] text = new String[4]; - for (byte i = 0; i < 4; i++) { - text[i] = signData.getText(i); - } - return text; - } - - /** - * Gets the contents of chests. Will return null if the chest does not - * really exist or it is the second block for a double chest. - * - * @param pt - * @return - */ - public BaseItemStack[] getChestContents(LocalWorld world, Vector pt) { - ComplexBlock cblock = etc.getServer().getOnlyComplexBlock( - pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - - BaseItemStack[] items; - Item[] nativeItems; - - if (cblock instanceof Chest) { - Chest chest = (Chest)cblock; - nativeItems = chest.getContents(); - } else { - return null; - } - - items = new BaseItemStack[nativeItems.length]; - - for (byte i = 0; i < nativeItems.length; i++) { - Item item = nativeItems[i]; - - if (item != null) { - items[i] = new BaseItemStack((short)item.getItemId(), - item.getAmount(), (short)item.getDamage()); - } - } - - return items; - } - - /** - * Sets a chest slot. - * - * @param pt - * @param contents - * @return - */ - public boolean setChestContents(LocalWorld world, Vector pt, - BaseItemStack[] contents) { - - ComplexBlock cblock = etc.getServer().getOnlyComplexBlock( - pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - - if (cblock instanceof Chest) { - Chest chest = (Chest)cblock; - Item[] nativeItems = new Item[contents.length]; - - for (int i = 0; i < contents.length; i++) { - BaseItemStack item = contents[i]; - - if (item != null) { - Item nativeItem = - new Item(item.getID(), item.getAmount()); - nativeItem.setDamage(item.getDamage()); - nativeItems[i] = nativeItem; - } - } - - setContents(chest, nativeItems); - } - - return false; - } - - /** - * Clear a chest's contents. - * - * @param pt - */ - public boolean clearChest(LocalWorld world, Vector pt) { - ComplexBlock cblock = etc.getServer().getOnlyComplexBlock( - pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - - if (cblock instanceof Chest) { - Chest chest = (Chest)cblock; - chest.clearContents(); - chest.update(); - return true; - } - - - return false; - } - - /** - * Set the contents of an ItemArray. - * - * @param itemArray - * @param contents - */ - private void setContents(ItemArray itemArray, Item[] contents) { - int size = contents.length; - - for (int i = 0; i < size; i++) { - if (contents[i] == null) { - itemArray.removeItem(i); - } else { - itemArray.setSlot(contents[i].getItemId(), - contents[i].getAmount(), contents[i].getDamage(), i); - } - } - } - - /** - * Checks if a mob type is valid. - * - * @param type - * @return - */ - public boolean isValidMobType(String type) { - return Mob.isValid(type); - } - - /** - * Set mob spawner mob type. - * - * @param pt - * @param mobType - */ - public void setMobSpawnerType(LocalWorld world, Vector pt, String mobType) { - ComplexBlock cblock = etc.getServer().getComplexBlock( - pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - - if (!(cblock instanceof MobSpawner)) { - return; - } - - MobSpawner mobSpawner = (MobSpawner)cblock; - mobSpawner.setSpawn(mobType); - mobSpawner.update(); - } - - /** - * Get mob spawner mob type. May return an empty string. - * - * @param pt - * @param mobType - */ - public String getMobSpawnerType(LocalWorld world, Vector pt) { - try { - return MinecraftServerInterface.getMobSpawnerType(pt); - } catch (Throwable t) { - logger.severe("Failed to get mob spawner type (do you need to update WorldEdit due to a Minecraft update?): " - + t.getMessage()); - return ""; - } - } - - /** - * Generate a tree at a location. - * - * @param pt - * @return - */ - public boolean generateTree(EditSession editSession, LocalWorld world, Vector pt) { - try { - return MinecraftServerInterface.generateTree(editSession, pt); - } catch (Throwable t) { - logger.severe("Failed to create tree (do you need to update WorldEdit due to a Minecraft update?): " - + t.getMessage()); - return false; - } - } - - /** - * Drop an item. - * - * @param pt - * @param type - * @param count - * @param times - */ - public void dropItem(LocalWorld world, Vector pt, int type, int count, int times) { - for (int i = 0; i < times; i++) { - etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), - type, count); - } - } - - /** - * Drop an item. - * - * @param pt - * @param type - * @param count - * @param times - */ - public void dropItem(LocalWorld world, Vector pt, int type, int count) { - etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), - type, count); - } - - /** - * Drop an item. - * - * @param pt - * @param type - * @param count - * @param times - */ - public void dropItem(LocalWorld world, Vector pt, int type) { - etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), - type, 1); - } - - /** - * Simulate a block being mined. - * - * @param pt - */ - public void simulateBlockMine(LocalWorld world, Vector pt) { - int type = getBlockType(world, pt); - //setBlockType(world, pt, 0); - - if (type == 1) { dropItem(world, pt, 4); } // Stone - else if (type == 2) { dropItem(world, pt, 3); } // Grass - else if (type == 7) { } // Bedrock - else if (type == 8) { } // Water - else if (type == 9) { } // Water - else if (type == 10) { } // Lava - else if (type == 11) { } // Lava - else if (type == 13) { // Gravel - dropItem(world, pt, type); - - if (random.nextDouble() >= 0.9) { - dropItem(world, pt, 318); - } - } - else if (type == 16) { dropItem(world, pt, 263); } // Coal ore - else if (type == 18) { // Leaves - if (random.nextDouble() > 0.95) { - dropItem(world, pt, 6); - } - } - else if (type == 20) { } // Glass - else if (type == 43) { dropItem(world, pt, 44); } // Double step - else if (type == 47) { } // Bookshelves - else if (type == 51) { } // Fire - else if (type == 52) { } // Mob spawner - else if (type == 53) { dropItem(world, pt, 5); } // Wooden stairs - else if (type == 55) { dropItem(world, pt, 331); } // Redstone wire - else if (type == 56) { dropItem(world, pt, 264); } // Diamond ore - else if (type == 59) { dropItem(world, pt, 295); } // Crops - else if (type == 60) { dropItem(world, pt, 3); } // Soil - else if (type == 62) { dropItem(world, pt, 61); } // Furnace - else if (type == 63) { dropItem(world, pt, 323); } // Sign post - else if (type == 64) { dropItem(world, pt, 324); } // Wood door - else if (type == 67) { dropItem(world, pt, 4); } // Cobblestone stairs - else if (type == 68) { dropItem(world, pt, 323); } // Wall sign - else if (type == 71) { dropItem(world, pt, 330); } // Iron door - else if (type == 73) { dropItem(world, pt, 331, 1, 4); } // Redstone ore - else if (type == 74) { dropItem(world, pt, 331, 1, 4); } // Glowing redstone ore - else if (type == 75) { dropItem(world, pt, 76); } // Redstone torch - else if (type == 78) { } // Snow - else if (type == 79) { } // Ice - else if (type == 82) { dropItem(world, pt, 337, 1, 4); } // Clay - else if (type == 83) { dropItem(world, pt, 338); } // Reed - else if (type == 89) { dropItem(world, pt, 348); } // Lightstone - else if (type == 90) { } // Portal - else if (type != 0) { - dropItem(world, pt, type); - } - } - /** * Resolves an item name to its ID. * @@ -403,24 +35,12 @@ public class HMServerInterface extends ServerInterface { } /** - * Kill mobs in an area. + * Checks if a mob type is valid. * - * @param origin - * @param radius + * @param type * @return */ - public int killMobs(LocalWorld world, Vector origin, int radius) { - int killed = 0; - - for (Mob mob : etc.getServer().getMobList()) { - Vector mobPos = new Vector(mob.getX(), mob.getY(), mob.getZ()); - if (mob.getHealth() > 0 - && (radius == -1 || mobPos.distance(origin) <= radius)) { - mob.setHealth(0); - killed++; - } - } - - return killed; + public boolean isValidMobType(String type) { + return Mob.isValid(type); } } diff --git a/src/HMWorld.java b/src/HMWorld.java new file mode 100644 index 000000000..3c0d3be96 --- /dev/null +++ b/src/HMWorld.java @@ -0,0 +1,419 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import java.util.Random; +import java.util.logging.Logger; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseItemStack; + +/** + * World for hMod. + * + * @author sk89q + */ +public class HMWorld extends LocalWorld { + /** + * Logger. + */ + private final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); + /** + * Random generator. + */ + private Random random = new Random(); + + /** + * Set block type. + * + * @param pt + * @param type + * @return + */ + public boolean setBlockType(Vector pt, int type) { + // Can't set colored cloth or crash + if ((type >= 21 && type <= 34) || type == 36) { + return false; + } + return etc.getServer().setBlockAt(type, pt.getBlockX(), pt.getBlockY(), + pt.getBlockZ()); + } + + /** + * Get block type. + * + * @param pt + * @return + */ + public int getBlockType(Vector pt) { + return etc.getServer().getBlockIdAt(pt.getBlockX(), pt.getBlockY(), + pt.getBlockZ()); + } + + /** + * Set block data. + * + * @param pt + * @param data + * @return + */ + public void setBlockData(Vector pt, int data) { + etc.getServer().setBlockData(pt.getBlockX(), pt.getBlockY(), + pt.getBlockZ(), data); + } + + /** + * Get block data. + * + * @param pt + * @return + */ + public int getBlockData(Vector pt) { + return etc.getServer().getBlockData(pt.getBlockX(), pt.getBlockY(), + pt.getBlockZ()); + } + + /** + * Set sign text. + * + * @param pt + * @param text + */ + public void setSignText(Vector pt, String[] text) { + Sign signData = (Sign)etc.getServer().getComplexBlock( + pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (signData == null) { + return; + } + for (byte i = 0; i < 4; i++) { + signData.setText(i, text[i]); + } + signData.update(); + } + + /** + * Get sign text. + * + * @param pt + * @return + */ + public String[] getSignText(Vector pt) { + Sign signData = (Sign)etc.getServer().getComplexBlock( + pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (signData == null) { + return new String[]{"", "", "", ""}; + } + String[] text = new String[4]; + for (byte i = 0; i < 4; i++) { + text[i] = signData.getText(i); + } + return text; + } + + /** + * Gets the contents of chests. Will return null if the chest does not + * really exist or it is the second block for a double chest. + * + * @param pt + * @return + */ + public BaseItemStack[] getChestContents(Vector pt) { + ComplexBlock cblock = etc.getServer().getOnlyComplexBlock( + pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + + BaseItemStack[] items; + Item[] nativeItems; + + if (cblock instanceof Chest) { + Chest chest = (Chest)cblock; + nativeItems = chest.getContents(); + } else { + return null; + } + + items = new BaseItemStack[nativeItems.length]; + + for (byte i = 0; i < nativeItems.length; i++) { + Item item = nativeItems[i]; + + if (item != null) { + items[i] = new BaseItemStack((short)item.getItemId(), + item.getAmount(), (short)item.getDamage()); + } + } + + return items; + } + + /** + * Sets a chest slot. + * + * @param pt + * @param contents + * @return + */ + public boolean setChestContents(Vector pt, + BaseItemStack[] contents) { + + ComplexBlock cblock = etc.getServer().getOnlyComplexBlock( + pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + + if (cblock instanceof Chest) { + Chest chest = (Chest)cblock; + Item[] nativeItems = new Item[contents.length]; + + for (int i = 0; i < contents.length; i++) { + BaseItemStack item = contents[i]; + + if (item != null) { + Item nativeItem = + new Item(item.getID(), item.getAmount()); + nativeItem.setDamage(item.getDamage()); + nativeItems[i] = nativeItem; + } + } + + setContents(chest, nativeItems); + } + + return false; + } + + /** + * Clear a chest's contents. + * + * @param pt + */ + public boolean clearChest(Vector pt) { + ComplexBlock cblock = etc.getServer().getOnlyComplexBlock( + pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + + if (cblock instanceof Chest) { + Chest chest = (Chest)cblock; + chest.clearContents(); + chest.update(); + return true; + } + + + return false; + } + + /** + * Set the contents of an ItemArray. + * + * @param itemArray + * @param contents + */ + private void setContents(ItemArray itemArray, Item[] contents) { + int size = contents.length; + + for (int i = 0; i < size; i++) { + if (contents[i] == null) { + itemArray.removeItem(i); + } else { + itemArray.setSlot(contents[i].getItemId(), + contents[i].getAmount(), contents[i].getDamage(), i); + } + } + } + + /** + * Set mob spawner mob type. + * + * @param pt + * @param mobType + */ + public void setMobSpawnerType(Vector pt, String mobType) { + ComplexBlock cblock = etc.getServer().getComplexBlock( + pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + + if (!(cblock instanceof MobSpawner)) { + return; + } + + MobSpawner mobSpawner = (MobSpawner)cblock; + mobSpawner.setSpawn(mobType); + mobSpawner.update(); + } + + /** + * Get mob spawner mob type. May return an empty string. + * + * @param pt + * @param mobType + */ + public String getMobSpawnerType(Vector pt) { + try { + return MinecraftServerInterface.getMobSpawnerType(pt); + } catch (Throwable t) { + logger.severe("Failed to get mob spawner type (do you need to update WorldEdit due to a Minecraft update?): " + + t.getMessage()); + return ""; + } + } + + /** + * Generate a tree at a location. + * + * @param pt + * @return + */ + public boolean generateTree(EditSession editSession, Vector pt) { + try { + return MinecraftServerInterface.generateTree(editSession, pt); + } catch (Throwable t) { + logger.severe("Failed to create tree (do you need to update WorldEdit due to a Minecraft update?): " + + t.getMessage()); + return false; + } + } + + /** + * Drop an item. + * + * @param pt + * @param type + * @param count + * @param times + */ + public void dropItem(Vector pt, int type, int count, int times) { + for (int i = 0; i < times; i++) { + etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), + type, count); + } + } + + /** + * Drop an item. + * + * @param pt + * @param type + * @param count + * @param times + */ + public void dropItem(Vector pt, int type, int count) { + etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), + type, count); + } + + /** + * Drop an item. + * + * @param pt + * @param type + * @param count + * @param times + */ + public void dropItem(Vector pt, int type) { + etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), + type, 1); + } + + /** + * Simulate a block being mined. + * + * @param pt + */ + public void simulateBlockMine(Vector pt) { + int type = getBlockType(pt); + //setBlockType(pt, 0); + + if (type == 1) { dropItem(pt, 4); } // Stone + else if (type == 2) { dropItem(pt, 3); } // Grass + else if (type == 7) { } // Bedrock + else if (type == 8) { } // Water + else if (type == 9) { } // Water + else if (type == 10) { } // Lava + else if (type == 11) { } // Lava + else if (type == 13) { // Gravel + dropItem(pt, type); + + if (random.nextDouble() >= 0.9) { + dropItem(pt, 318); + } + } + else if (type == 16) { dropItem(pt, 263); } // Coal ore + else if (type == 18) { // Leaves + if (random.nextDouble() > 0.95) { + dropItem(pt, 6); + } + } + else if (type == 20) { } // Glass + else if (type == 43) { dropItem(pt, 44); } // Double step + else if (type == 47) { } // Bookshelves + else if (type == 51) { } // Fire + else if (type == 52) { } // Mob spawner + else if (type == 53) { dropItem(pt, 5); } // Wooden stairs + else if (type == 55) { dropItem(pt, 331); } // Redstone wire + else if (type == 56) { dropItem(pt, 264); } // Diamond ore + else if (type == 59) { dropItem(pt, 295); } // Crops + else if (type == 60) { dropItem(pt, 3); } // Soil + else if (type == 62) { dropItem(pt, 61); } // Furnace + else if (type == 63) { dropItem(pt, 323); } // Sign post + else if (type == 64) { dropItem(pt, 324); } // Wood door + else if (type == 67) { dropItem(pt, 4); } // Cobblestone stairs + else if (type == 68) { dropItem(pt, 323); } // Wall sign + else if (type == 71) { dropItem(pt, 330); } // Iron door + else if (type == 73) { dropItem(pt, 331, 1, 4); } // Redstone ore + else if (type == 74) { dropItem(pt, 331, 1, 4); } // Glowing redstone ore + else if (type == 75) { dropItem(pt, 76); } // Redstone torch + else if (type == 78) { } // Snow + else if (type == 79) { } // Ice + else if (type == 82) { dropItem(pt, 337, 1, 4); } // Clay + else if (type == 83) { dropItem(pt, 338); } // Reed + else if (type == 89) { dropItem(pt, 348); } // Lightstone + else if (type == 90) { } // Portal + else if (type != 0) { + dropItem(pt, type); + } + } + + /** + * Kill mobs in an area. + * + * @param origin + * @param radius + * @return + */ + public int killMobs(Vector origin, int radius) { + int killed = 0; + + for (Mob mob : etc.getServer().getMobList()) { + Vector mobPos = new Vector(mob.getX(), mob.getY(), mob.getZ()); + if (mob.getHealth() > 0 + && (radius == -1 || mobPos.distance(origin) <= radius)) { + mob.setHealth(0); + killed++; + } + } + + return killed; + } + + @Override + public boolean equals(Object other) { + return other instanceof HMWorld; + } + + @Override + public int hashCode() { + return 1; + } +} diff --git a/src/HMWorldEditListener.java b/src/HMWorldEditListener.java index 91a9f57a1..e997b166f 100755 --- a/src/HMWorldEditListener.java +++ b/src/HMWorldEditListener.java @@ -39,6 +39,10 @@ public class HMWorldEditListener extends PluginListener { * will go through. */ private ServerInterface server; + /** + * A copy of a world, not that hMod/MC supports multiple worlds. + */ + private HMWorld world; /** * Constructs an instance. @@ -50,6 +54,7 @@ public class HMWorldEditListener extends PluginListener { config = new HMConfiguration(); controller = new WorldEditController(server, config); + world = new HMWorld(); } /** @@ -83,10 +88,9 @@ public class HMWorldEditListener extends PluginListener { @SuppressWarnings("deprecation") public boolean onBlockCreate(Player player, Block blockPlaced, Block blockClicked, int itemInHand) { - Vector pos = new Vector(blockClicked.getX(), - blockClicked.getY(), - blockClicked.getZ()); - return controller.handleBlockRightClick(wrapPlayer(player), null, pos); + WorldVector pos = new WorldVector(world, blockClicked.getX(), + blockClicked.getY(), blockClicked.getZ()); + return controller.handleBlockRightClick(wrapPlayer(player), pos); } /** @@ -99,10 +103,9 @@ public class HMWorldEditListener extends PluginListener { */ @Override public boolean onBlockDestroy(Player player, Block blockClicked) { - Vector pos = new Vector(blockClicked.getX(), - blockClicked.getY(), - blockClicked.getZ()); - return controller.handleBlockLeftClick(wrapPlayer(player), null, pos); + WorldVector pos = new WorldVector(world, blockClicked.getX(), + blockClicked.getY(), blockClicked.getZ()); + return controller.handleBlockLeftClick(wrapPlayer(player), pos); } /** @@ -167,6 +170,6 @@ public class HMWorldEditListener extends PluginListener { * @return */ private LocalPlayer wrapPlayer(Player player) { - return new HMPlayer(server, player); + return new HMPlayer(server, world, player); } } diff --git a/src/com/sk89q/worldedit/EditSession.java b/src/com/sk89q/worldedit/EditSession.java index 1d2f4c6a0..39d9f143f 100755 --- a/src/com/sk89q/worldedit/EditSession.java +++ b/src/com/sk89q/worldedit/EditSession.java @@ -50,10 +50,6 @@ public class EditSession { */ private static Random prng = new Random(); - /** - * Server interface. - */ - private ServerInterface server; /** * World. */ @@ -62,23 +58,28 @@ public class EditSession { /** * Stores the original blocks before modification. */ - private DoubleArrayList original = new DoubleArrayList( + private DoubleArrayList original = + new DoubleArrayList( true); /** * Stores the current blocks. */ - private DoubleArrayList current = new DoubleArrayList( + private DoubleArrayList current = + new DoubleArrayList( false); /** * Blocks that should be placed before last. */ - private DoubleArrayList queueAfter = new DoubleArrayList( + private DoubleArrayList queueAfter = + new DoubleArrayList( false); /** * Blocks that should be placed last. */ - private DoubleArrayList queueLast = new DoubleArrayList( + private DoubleArrayList queueLast = + new DoubleArrayList( false); + /** * The maximum number of blocks to change at a time. If this number is * exceeded, a MaxChangedBlocksException exception will be raised. -1 @@ -112,7 +113,6 @@ public class EditSession { } this.maxBlocks = maxBlocks; - this.server = server; this.world = world; } @@ -131,7 +131,6 @@ public class EditSession { this.maxBlocks = maxBlocks; this.blockBag = blockBag; - this.server = server; this.world = world; } @@ -149,14 +148,14 @@ public class EditSession { } // Clear the chest so that it doesn't drop items - if (server.getBlockType(world, pt) == 54 && blockBag == null) { - server.clearChest(world, pt); + if (world.getBlockType(pt) == 54 && blockBag == null) { + world.clearChest(pt); } int id = block.getID(); if (blockBag != null) { - int existing = server.getBlockType(world, pt); + int existing = world.getBlockType(pt); if (id > 0) { try { @@ -177,25 +176,25 @@ public class EditSession { } } - boolean result = server.setBlockType(world, pt, id); + boolean result = world.setBlockType(pt, id); if (id != 0) { if (BlockType.usesData(id)) { - server.setBlockData(world, pt, block.getData()); + world.setBlockData(pt, block.getData()); } // Signs if (block instanceof SignBlock) { SignBlock signBlock = (SignBlock) block; String[] text = signBlock.getText(); - server.setSignText(world, pt, text); + world.setSignText(pt, text); // Chests } else if (block instanceof ChestBlock && blockBag == null) { ChestBlock chestBlock = (ChestBlock) block; - server.setChestContents(world, pt, chestBlock.getItems()); + world.setChestContents(pt, chestBlock.getItems()); // Mob spawners } else if (block instanceof MobSpawnerBlock) { MobSpawnerBlock mobSpawnerblock = (MobSpawnerBlock) block; - server.setMobSpawnerType(world, pt, mobSpawnerblock.getMobType()); + world.setMobSpawnerType(pt, mobSpawnerblock.getMobType()); } } @@ -298,21 +297,20 @@ public class EditSession { * @return BaseBlock */ public BaseBlock rawGetBlock(Vector pt) { - int type = server.getBlockType(world, pt); - int data = server.getBlockData(world, pt); + int type = world.getBlockType(pt); + int data = world.getBlockData(pt); // Sign if (type == 63 || type == 68) { - String[] text = server.getSignText(world, pt); + String[] text = world.getSignText(pt); return new SignBlock(type, data, text); // Chest } else if (type == 54) { - BaseItemStack[] items = server.getChestContents(world, pt); + BaseItemStack[] items = world.getChestContents(pt); return new ChestBlock(data, items); // Mob spawner } else if (type == 52) { - return new MobSpawnerBlock(data, - server.getMobSpawnerType(world, pt)); + return new MobSpawnerBlock(data, world.getMobSpawnerType(pt)); } else { return new BaseBlock(type, data); } @@ -1813,8 +1811,7 @@ public class EditSession { if (pineTree) { makePineTree(new Vector(x, y + 1, z)); } else { - server.generateTree(this, world, - new Vector(x, y + 1, z)); + world.generateTree(this, new Vector(x, y + 1, z)); } affected++; break; diff --git a/src/com/sk89q/worldedit/LocalPlayer.java b/src/com/sk89q/worldedit/LocalPlayer.java index d776c43a4..e1fb89cea 100644 --- a/src/com/sk89q/worldedit/LocalPlayer.java +++ b/src/com/sk89q/worldedit/LocalPlayer.java @@ -83,8 +83,7 @@ public abstract class LocalPlayer { byte free = 0; while (y <= 129) { - if (BlockType.canPassThrough(server.getBlockType(world, - new Vector(x, y, z)))) { + if (BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { free++; } else { free = 0; @@ -128,7 +127,7 @@ public abstract class LocalPlayer { byte spots = 0; while (y <= 129) { - if (BlockType.canPassThrough(server.getBlockType(world, new Vector(x, y, z)))) { + if (BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { free++; } else { free = 0; @@ -137,7 +136,7 @@ public abstract class LocalPlayer { if (free == 2) { spots++; if (spots == 2) { - int type = server.getBlockType(world, new Vector(x, y - 2, z)); + int type = world.getBlockType(new Vector(x, y - 2, z)); // Don't get put in lava! if (type == 10 || type == 11) { @@ -170,7 +169,7 @@ public abstract class LocalPlayer { byte free = 0; while (y >= 1) { - if (BlockType.canPassThrough(server.getBlockType(world, new Vector(x, y, z)))) { + if (BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { free++; } else { free = 0; @@ -181,7 +180,7 @@ public abstract class LocalPlayer { // lightly and also check to see if there's something to // stand upon while (y >= 0) { - int type = server.getBlockType(world, new Vector(x, y, z)); + int type = world.getBlockType(new Vector(x, y, z)); // Don't want to end up in lava if (type != 0 && type != 10 && type != 11) { @@ -217,15 +216,15 @@ public abstract class LocalPlayer { LocalWorld world = getPosition().getWorld(); // No free space above - if (server.getBlockType(world, new Vector(x, y, z)) != 0) { + if (world.getBlockType(new Vector(x, y, z)) != 0) { return false; } while (y <= 127) { // Found a ceiling! - if (!BlockType.canPassThrough(server.getBlockType(world, new Vector(x, y, z)))) { + if (!BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { int platformY = Math.max(initialY, y - 3 - clearance); - server.setBlockType(world, new Vector(x, platformY, z), + world.setBlockType(new Vector(x, platformY, z), BlockType.GLASS.getID()); setPosition(new Vector(x + 0.5, platformY + 1, z + 0.5)); return true; @@ -253,12 +252,12 @@ public abstract class LocalPlayer { LocalWorld world = getPosition().getWorld(); while (y <= 129) { - if (!BlockType.canPassThrough(server.getBlockType(world, new Vector(x, y, z)))) { + if (!BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { break; // Hit something } else if (y > maxY + 1) { break; } else if (y == maxY + 1) { - server.setBlockType(world, new Vector(x, y - 2, z), + world.setBlockType(new Vector(x, y - 2, z), BlockType.GLASS.getID()); setPosition(new Vector(x + 0.5, y - 1, z + 0.5)); return true; diff --git a/src/com/sk89q/worldedit/LocalWorld.java b/src/com/sk89q/worldedit/LocalWorld.java index 74bda7fef..59c4956a5 100644 --- a/src/com/sk89q/worldedit/LocalWorld.java +++ b/src/com/sk89q/worldedit/LocalWorld.java @@ -19,12 +19,163 @@ package com.sk89q.worldedit; +import com.sk89q.worldedit.blocks.BaseItemStack; + /** * Represents a world. * * @author sk89q */ public abstract class LocalWorld { + /** + * Set block type. + * + * @param pt + * @param type + * @return + */ + public abstract boolean setBlockType(Vector pt, int type); + + /** + * Get block type. + * + * @param pt + * @return + */ + public abstract int getBlockType(Vector pt); + + /** + * Set block data. + * + * @param pt + * @param data + * @return + */ + public abstract void setBlockData(Vector pt, int data); + + /** + * Get block data. + * + * @param pt + * @return + */ + public abstract int getBlockData(Vector pt); + + /** + * Set sign text. + * + * @param pt + * @param text + */ + public abstract void setSignText(Vector pt, String[] text); + + /** + * Get sign text. + * + * @param pt + * @return + */ + public abstract String[] getSignText(Vector pt); + + /** + * Gets the contents of chests. Will return null if the chest does not + * really exist or it is the second block for a double chest. + * + * @param pt + * @return + */ + public abstract BaseItemStack[] getChestContents(Vector pt); + + /** + * Sets a chest slot. + * + * @param pt + * @param contents + * @return + */ + public abstract boolean setChestContents(Vector pt, + BaseItemStack[] contents); + + /** + * Clear a chest's contents. + * + * @param pt + */ + public abstract boolean clearChest(Vector pt); + + /** + * Set mob spawner mob type. + * + * @param pt + * @param mobType + */ + public abstract void setMobSpawnerType(Vector pt, + String mobType); + + /** + * Get mob spawner mob type. May return an empty string. + * + * @param pt + * @param mobType + */ + public abstract String getMobSpawnerType(Vector pt); + + /** + * Generate a tree at a location. + * + * @param pt + * @return + */ + public abstract boolean generateTree(EditSession editSession, Vector pt); + + /** + * Drop an item. + * + * @param pt + * @param type + * @param count + * @param times + */ + public abstract void dropItem(Vector pt, int type, + int count, int times); + + /** + * Drop an item. + * + * @param pt + * @param type + * @param count + * @param times + */ + public abstract void dropItem(Vector pt, int type, + int count); + + /** + * Drop an item. + * + * @param pt + * @param type + * @param count + * @param times + */ + public abstract void dropItem(Vector pt, int type); + + /** + * Simulate a block being mined. + * + * @param pt + */ + public abstract void simulateBlockMine(Vector pt); + + /** + * Kill mobs in an area. + * + * @param origin + * @param radius + * @return + */ + public abstract int killMobs(Vector origin, int radius); + /** * Compare if the other world is equal. * diff --git a/src/com/sk89q/worldedit/ServerInterface.java b/src/com/sk89q/worldedit/ServerInterface.java index 9934e69bc..44121cbd8 100644 --- a/src/com/sk89q/worldedit/ServerInterface.java +++ b/src/com/sk89q/worldedit/ServerInterface.java @@ -19,162 +19,11 @@ package com.sk89q.worldedit; -import com.sk89q.worldedit.blocks.BaseItemStack; - /** * * @author sk89q */ public abstract class ServerInterface { - /** - * Set block type. - * - * @param pt - * @param type - * @return - */ - public abstract boolean setBlockType(LocalWorld world, Vector pt, int type); - - /** - * Get block type. - * - * @param pt - * @return - */ - public abstract int getBlockType(LocalWorld world, Vector pt); - - /** - * Set block data. - * - * @param pt - * @param data - * @return - */ - public abstract void setBlockData(LocalWorld world, Vector pt, int data); - - /** - * Get block data. - * - * @param pt - * @return - */ - public abstract int getBlockData(LocalWorld world, Vector pt); - - /** - * Set sign text. - * - * @param pt - * @param text - */ - public abstract void setSignText(LocalWorld world, Vector pt, String[] text); - - /** - * Get sign text. - * - * @param pt - * @return - */ - public abstract String[] getSignText(LocalWorld world, Vector pt); - - /** - * Gets the contents of chests. Will return null if the chest does not - * really exist or it is the second block for a double chest. - * - * @param pt - * @return - */ - public abstract BaseItemStack[] getChestContents(LocalWorld world, Vector pt); - - /** - * Sets a chest slot. - * - * @param pt - * @param contents - * @return - */ - public abstract boolean setChestContents(LocalWorld world, Vector pt, - BaseItemStack[] contents); - - /** - * Clear a chest's contents. - * - * @param pt - */ - public abstract boolean clearChest(LocalWorld world, Vector pt); - - /** - * Checks if a mob type is valid. - * - * @param type - * @return - */ - public abstract boolean isValidMobType(String type); - - /** - * Set mob spawner mob type. - * - * @param pt - * @param mobType - */ - public abstract void setMobSpawnerType(LocalWorld world, Vector pt, - String mobType); - - /** - * Get mob spawner mob type. May return an empty string. - * - * @param pt - * @param mobType - */ - public abstract String getMobSpawnerType(LocalWorld world, Vector pt); - - /** - * Generate a tree at a location. - * - * @param pt - * @return - */ - public abstract boolean generateTree(EditSession editSession, - LocalWorld world, Vector pt); - - /** - * Drop an item. - * - * @param pt - * @param type - * @param count - * @param times - */ - public abstract void dropItem(LocalWorld world, Vector pt, int type, - int count, int times); - - /** - * Drop an item. - * - * @param pt - * @param type - * @param count - * @param times - */ - public abstract void dropItem(LocalWorld world, Vector pt, int type, - int count); - - /** - * Drop an item. - * - * @param pt - * @param type - * @param count - * @param times - */ - public abstract void dropItem(LocalWorld world, Vector pt, int type); - - /** - * Simulate a block being mined. - * - * @param pt - */ - public abstract void simulateBlockMine(LocalWorld world, Vector pt); - /** * Resolves an item name to its ID. * @@ -182,13 +31,12 @@ public abstract class ServerInterface { * @return */ public abstract int resolveItem(String name); - + /** - * Kill mobs in an area. + * Checks if a mob type is valid. * - * @param origin - * @param radius + * @param type * @return */ - public abstract int killMobs(LocalWorld world, Vector origin, int radius); + public abstract boolean isValidMobType(String type); } diff --git a/src/com/sk89q/worldedit/WorldEditController.java b/src/com/sk89q/worldedit/WorldEditController.java index d08902ac5..a0744a711 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -436,6 +436,8 @@ public class WorldEditController { logger.log(Level.INFO, "WorldEdit: " + player.getName() + ": " + joinString(split, " ")); } + + LocalWorld world = player.getPosition().getWorld(); // Jump to the first free position if (split[0].equalsIgnoreCase("/unstuck")) { @@ -1359,7 +1361,7 @@ public class WorldEditController { Math.max(1, Integer.parseInt(split[1])) : -1; Vector origin = session.getPlacementPosition(player); - int killed = server.killMobs(player.getWorld(), origin, radius); + int killed = world.killMobs(origin, radius); player.print("Killed " + killed + " mobs."); return true; @@ -1741,12 +1743,10 @@ public class WorldEditController { * Called on right click. * * @param player - * @param world * @param clicked * @return false if you want the action to go through */ - public boolean handleBlockRightClick(LocalPlayer player, LocalWorld world, - Vector clicked) { + public boolean handleBlockRightClick(LocalPlayer player, WorldVector clicked) { int itemInHand = player.getItemInHand(); // This prevents needless sessions from being created @@ -1767,8 +1767,7 @@ public class WorldEditController { return true; } else if (player.isHoldingPickAxe() && session.getTool() != null) { - return session.getTool().act(server, config, player, session, - world, clicked); + return session.getTool().act(server, config, player, session, clicked); } return false; @@ -1778,12 +1777,10 @@ public class WorldEditController { * Called on left click. * * @param player - * @param world * @param clicked * @return false if you want the action to go through */ - public boolean handleBlockLeftClick(LocalPlayer player, - LocalWorld world, Vector clicked) { + public boolean handleBlockLeftClick(LocalPlayer player, WorldVector clicked) { if (!canUseCommand(player, "/pos1") && !canUseCommand(player, "/")) { return false; } @@ -1818,7 +1815,7 @@ public class WorldEditController { } else if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) { if (session.getSuperPickaxeMode() != null) { return session.getSuperPickaxeMode().act(server, config, - player, session, world, clicked); + player, session, clicked); } } diff --git a/src/com/sk89q/worldedit/superpickaxe/AreaPickaxe.java b/src/com/sk89q/worldedit/superpickaxe/AreaPickaxe.java index 7f3d6fbec..fa5af2980 100644 --- a/src/com/sk89q/worldedit/superpickaxe/AreaPickaxe.java +++ b/src/com/sk89q/worldedit/superpickaxe/AreaPickaxe.java @@ -38,12 +38,12 @@ public class AreaPickaxe implements SuperPickaxeMode { @Override public boolean act(ServerInterface server, LocalConfiguration config, - LocalPlayer player, LocalSession session, LocalWorld world, - Vector clicked) { + LocalPlayer player, LocalSession session, WorldVector clicked) { + LocalWorld world = clicked.getWorld(); int ox = clicked.getBlockX(); int oy = clicked.getBlockY(); int oz = clicked.getBlockZ(); - int initialType = server.getBlockType(world, clicked); + int initialType = world.getBlockType(clicked); if (initialType == 0) { return true; @@ -61,9 +61,9 @@ public class AreaPickaxe implements SuperPickaxeMode { for (int y = oy - range; y <= oy + range; y++) { for (int z = oz - range; z <= oz + range; z++) { Vector pos = new Vector(x, y, z); - if (server.getBlockType(world, pos) == initialType) { + if (world.getBlockType(pos) == initialType) { if (config.superPickaxeManyDrop) { - server.simulateBlockMine(world, pos); + world.simulateBlockMine(pos); } editSession.setBlock(pos, air); diff --git a/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java b/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java index d803ffac7..10c017480 100644 --- a/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java +++ b/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java @@ -36,9 +36,9 @@ public class BlockReplacer implements SuperPickaxeMode { @Override public boolean act(ServerInterface server, LocalConfiguration config, - LocalPlayer player, LocalSession session, LocalWorld world, - Vector clicked) { + LocalPlayer player, LocalSession session, WorldVector clicked) { + LocalWorld world = clicked.getWorld(); EditSession editSession = new EditSession(server, world, -1); try { diff --git a/src/com/sk89q/worldedit/superpickaxe/QueryTool.java b/src/com/sk89q/worldedit/superpickaxe/QueryTool.java index 524c4695f..d960e2bd3 100644 --- a/src/com/sk89q/worldedit/superpickaxe/QueryTool.java +++ b/src/com/sk89q/worldedit/superpickaxe/QueryTool.java @@ -31,8 +31,9 @@ public class QueryTool implements SuperPickaxeMode { @Override public boolean act(ServerInterface server, LocalConfiguration config, - LocalPlayer player, LocalSession session, LocalWorld world, - Vector clicked) { + LocalPlayer player, LocalSession session, WorldVector clicked) { + + LocalWorld world = clicked.getWorld(); BaseBlock block = (new EditSession(server, world, 0)).rawGetBlock(clicked); player.print("\u00A79@" + clicked + ": " + "\u00A7e" diff --git a/src/com/sk89q/worldedit/superpickaxe/RecursivePickaxe.java b/src/com/sk89q/worldedit/superpickaxe/RecursivePickaxe.java index 077050c68..baaef70cb 100644 --- a/src/com/sk89q/worldedit/superpickaxe/RecursivePickaxe.java +++ b/src/com/sk89q/worldedit/superpickaxe/RecursivePickaxe.java @@ -41,9 +41,10 @@ public class RecursivePickaxe implements SuperPickaxeMode { @Override public boolean act(ServerInterface server, LocalConfiguration config, - LocalPlayer player, LocalSession session, LocalWorld world, - Vector clicked) { - int initialType = server.getBlockType(world, clicked); + LocalPlayer player, LocalSession session, WorldVector clicked) { + LocalWorld world = clicked.getWorld(); + + int initialType = world.getBlockType(clicked); if (initialType == 0) { return true; @@ -95,7 +96,7 @@ public class RecursivePickaxe implements SuperPickaxeMode { if (editSession.getBlock(pos).getID() == initialType) { if (drop) { - server.simulateBlockMine(world, pos); + world.simulateBlockMine(pos); } editSession.setBlock(pos, air); } else { diff --git a/src/com/sk89q/worldedit/superpickaxe/SinglePickaxe.java b/src/com/sk89q/worldedit/superpickaxe/SinglePickaxe.java index fe85aa562..1d15ef531 100644 --- a/src/com/sk89q/worldedit/superpickaxe/SinglePickaxe.java +++ b/src/com/sk89q/worldedit/superpickaxe/SinglePickaxe.java @@ -30,21 +30,21 @@ import com.sk89q.worldedit.blocks.BlockID; public class SinglePickaxe implements SuperPickaxeMode { @Override public boolean act(ServerInterface server, LocalConfiguration config, - LocalPlayer player, LocalSession session, LocalWorld world, - Vector clicked) { + LocalPlayer player, LocalSession session, WorldVector clicked) { + LocalWorld world = clicked.getWorld(); - if (server.getBlockType(world, clicked) == BlockID.BEDROCK + if (world.getBlockType(clicked) == BlockID.BEDROCK && !player.canDestroyBedrock()) { return true; - } else if (server.getBlockType(world, clicked) == BlockID.TNT) { + } else if (world.getBlockType(clicked) == BlockID.TNT) { return false; } if (config.superPickaxeDrop) { - server.simulateBlockMine(world, clicked); + world.simulateBlockMine(clicked); } - server.setBlockType(world, clicked, 0); + world.setBlockType(clicked, 0); return true; } diff --git a/src/com/sk89q/worldedit/superpickaxe/SuperPickaxeMode.java b/src/com/sk89q/worldedit/superpickaxe/SuperPickaxeMode.java index f8835c549..7919022b3 100644 --- a/src/com/sk89q/worldedit/superpickaxe/SuperPickaxeMode.java +++ b/src/com/sk89q/worldedit/superpickaxe/SuperPickaxeMode.java @@ -37,6 +37,5 @@ public interface SuperPickaxeMode { * @return true to deny */ public boolean act(ServerInterface server, LocalConfiguration config, - LocalPlayer player, LocalSession session, LocalWorld world, - Vector clicked); + LocalPlayer player, LocalSession session, WorldVector clicked); } diff --git a/src/com/sk89q/worldedit/superpickaxe/TreePlanter.java b/src/com/sk89q/worldedit/superpickaxe/TreePlanter.java index 67a40ce4b..4f9b1a1af 100644 --- a/src/com/sk89q/worldedit/superpickaxe/TreePlanter.java +++ b/src/com/sk89q/worldedit/superpickaxe/TreePlanter.java @@ -30,13 +30,14 @@ public class TreePlanter implements SuperPickaxeMode { @Override public boolean act(ServerInterface server, LocalConfiguration config, - LocalPlayer player, LocalSession session, LocalWorld world, - Vector clicked) { + LocalPlayer player, LocalSession session, WorldVector clicked) { + + LocalWorld world = clicked.getWorld(); EditSession editSession = new EditSession(server, world, session.getBlockChangeLimit()); try { - if (!server.generateTree(editSession, player.getWorld(), clicked)) { + if (!world.generateTree(editSession, clicked)) { player.printError("Notch won't let you put a tree there."); } } finally { From 1767597672c75756d8c7db21d48f53167418ec20 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 11:30:05 -0800 Subject: [PATCH 08/13] Fixed WorldEdit not handling ice removal well. --- src/com/sk89q/worldedit/EditSession.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/com/sk89q/worldedit/EditSession.java b/src/com/sk89q/worldedit/EditSession.java index 39d9f143f..c081a1c6c 100755 --- a/src/com/sk89q/worldedit/EditSession.java +++ b/src/com/sk89q/worldedit/EditSession.java @@ -143,20 +143,24 @@ public class EditSession { */ private boolean rawSetBlock(Vector pt, BaseBlock block) { int y = pt.getBlockY(); + if (y < 0 || y > 127) { return false; } + + int existing = world.getBlockType(pt); // Clear the chest so that it doesn't drop items - if (world.getBlockType(pt) == 54 && blockBag == null) { + if (existing == 54 && blockBag == null) { world.clearChest(pt); + // Ice turns until water so this has to be done first + } else if (existing == BlockID.ICE) { + world.setBlockType(pt, 0); } int id = block.getID(); if (blockBag != null) { - int existing = world.getBlockType(pt); - if (id > 0) { try { blockBag.fetchPlacedBlock(id); From d55fa96e3e59274b3182a4bb7fce814e7edad1aa Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 11:40:18 -0800 Subject: [PATCH 09/13] Added /thaw. --- src/com/sk89q/worldedit/EditSession.java | 48 +++++++++++++++++++ .../sk89q/worldedit/WorldEditController.java | 11 +++++ 2 files changed, 59 insertions(+) diff --git a/src/com/sk89q/worldedit/EditSession.java b/src/com/sk89q/worldedit/EditSession.java index c081a1c6c..e20049ec5 100755 --- a/src/com/sk89q/worldedit/EditSession.java +++ b/src/com/sk89q/worldedit/EditSession.java @@ -1570,6 +1570,54 @@ public class EditSession { return affected; } + /** + * Thaw. + * + * @param pos + * @param radius + * @return number of blocks affected + * @throws MaxChangedBlocksException + */ + public int thaw(Vector pos, int radius) + throws MaxChangedBlocksException { + int affected = 0; + int radiusSq = (int)Math.pow(radius, 2); + + int ox = pos.getBlockX(); + int oy = pos.getBlockY(); + int oz = pos.getBlockZ(); + + BaseBlock air = new BaseBlock(0); + BaseBlock water = new BaseBlock(BlockID.STATIONARY_WATER); + + for (int x = ox - radius; x <= ox + radius; x++) { + for (int z = oz - radius; z <= oz + radius; z++) { + if ((new Vector(x, oy, z)).distanceSq(pos) > radiusSq) { + continue; + } + + for (int y = 127; y >= 1; y--) { + Vector pt = new Vector(x, y, z); + int id = getBlock(pt).getID(); + + if (id == BlockID.ICE) { // Ice + if (setBlock(pt, water)) { + affected++; + } + } else if (id == BlockID.SNOW) { + if (setBlock(pt, air)) { + affected++; + } + } else if (id != 0) { + break; + } + } + } + } + + return affected; + } + /** * Make snow. * diff --git a/src/com/sk89q/worldedit/WorldEditController.java b/src/com/sk89q/worldedit/WorldEditController.java index a0744a711..d650617c5 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -155,6 +155,7 @@ public class WorldEditController { commands.put("/forestgen", " - Make Notch tree forest"); commands.put("/pinegen", " - Make an ugly pine tree forest"); commands.put("/snow", " - Simulate snow cover"); + commands.put("/thaw", " - Unthaw/remove snow"); commands.put("/pumpkins", " - Make a pumpkin forest"); commands.put("/unstuck", "Go up to the first free spot"); commands.put("/ascend", "Go up one level"); @@ -1219,6 +1220,16 @@ public class WorldEditController { return true; + // Thaw + } else if (split[0].equalsIgnoreCase("/thaw")) { + checkArgs(split, 0, 1, split[0]); + int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10; + + int affected = editSession.thaw(player.getBlockIn(), size); + player.print(affected + " surfaces thawed."); + + return true; + // Make pumpkin patches } else if (split[0].equalsIgnoreCase("/pumpkins")) { checkArgs(split, 0, 1, split[0]); From 7a2f1b58e21f440da3d5b54df77a3652f1668b8b Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 11:41:22 -0800 Subject: [PATCH 10/13] Fixed the tree generator. --- src/MinecraftServerInterface.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MinecraftServerInterface.java b/src/MinecraftServerInterface.java index ac533d8fb..a1db0c1ea 100644 --- a/src/MinecraftServerInterface.java +++ b/src/MinecraftServerInterface.java @@ -62,7 +62,7 @@ public class MinecraftServerInterface { bt treeGen = new ib(); return treeGen.a(proxy, random, - pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + pt.getBlockX(), pt.getBlockY() + 1, pt.getBlockZ()); } /** From e57b89c0daf59ba5353640b2e34f8c911e1b373b Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 12:14:55 -0800 Subject: [PATCH 11/13] Removed 'air' prefix from commands, made /worldeditselect permission more encompassing, and added syntax for //expand and //expand vert|vertical. --- .../sk89q/worldedit/WorldEditController.java | 82 +++++++++++++------ 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/com/sk89q/worldedit/WorldEditController.java b/src/com/sk89q/worldedit/WorldEditController.java index d650617c5..418a3fc71 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -92,8 +92,6 @@ public class WorldEditController { this.server = server; this.config = config; - // Note: Commands should only have the phrase 'air' at the end - // for now (see SMWorldEditListener.canUseCommand) commands.put("//pos1", "Set editing position #1"); commands.put("//pos2", "Set editing position #2"); commands.put("//hpos1", "Trace editing position #1"); @@ -122,11 +120,8 @@ public class WorldEditController { commands.put("//copy", "Copies the currently selected region"); commands.put("//cut", "Cuts the currently selected region"); commands.put("//paste", " - Pastes the clipboard"); - commands.put("//pasteair", " - Pastes the clipboard (with air)"); commands.put("//move", " - Move the selection"); - commands.put("//moveair", " - Move the selection (with air)"); commands.put("//stack", " - Stacks the selection"); - commands.put("//stackair", " - Stacks the selection (with air)"); commands.put("//load", "[Filename] - Load .schematic into clipboard"); commands.put("//save", "[Filename] - Save clipboard to .schematic"); commands.put("//fill", "[ID] [Radius] - Fill a hole"); @@ -750,8 +745,7 @@ public class WorldEditController { return true; // Paste - } else if (split[0].equalsIgnoreCase("//pasteair") || - split[0].equalsIgnoreCase("//paste")) { + } else if (split[0].equalsIgnoreCase("//paste")) { checkArgs(split, 0, 1, split[0]); boolean atOrigin = split.length > 1 ? (split[1].equalsIgnoreCase("true") @@ -759,14 +753,12 @@ public class WorldEditController { : false; if (atOrigin) { Vector pos = session.getClipboard().getOrigin(); - session.getClipboard().place(editSession, pos, - split[0].equalsIgnoreCase("//paste")); + session.getClipboard().place(editSession, pos, false); player.findFreePosition(); player.print("Pasted to copy origin. Undo with //undo"); } else { Vector pos = session.getPlacementPosition(player); - session.getClipboard().paste(editSession, pos, - split[0].equalsIgnoreCase("//paste")); + session.getClipboard().paste(editSession, pos, false); player.findFreePosition(); player.print("Pasted relative to you. Undo with //undo"); } @@ -1241,8 +1233,7 @@ public class WorldEditController { return true; // Move - } else if (split[0].equalsIgnoreCase("//moveair") || - split[0].equalsIgnoreCase("//move")) { + } else if (split[0].equalsIgnoreCase("//move")) { checkArgs(split, 0, 3, split[0]); int count = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; Vector dir = getDirection(player, @@ -1255,37 +1246,55 @@ public class WorldEditController { } else { replace = new BaseBlock(0); } - - boolean copyAir = split[0].equalsIgnoreCase("//moveair"); int affected = editSession.moveCuboidRegion(session.getRegion(), - dir, count, copyAir, replace); + dir, count, true, replace); player.print(affected + " blocks moved."); return true; // Stack - } else if (split[0].equalsIgnoreCase("//stackair") || - split[0].equalsIgnoreCase("//stack")) { + } else if (split[0].equalsIgnoreCase("//stack")) { checkArgs(split, 0, 2, split[0]); int count = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1; Vector dir = getDirection(player, split.length > 2 ? split[2].toLowerCase() : "me"); - boolean copyAir = split[0].equalsIgnoreCase("//stackair"); int affected = editSession.stackCuboidRegion(session.getRegion(), - dir, count, copyAir); + dir, count, true); player.print(affected + " blocks changed. Undo with //undo"); return true; // Expand } else if (split[0].equalsIgnoreCase("//expand")) { - checkArgs(split, 1, 2, split[0]); + checkArgs(split, 1, 3, split[0]); Vector dir; + + if (split[1].equals("vert") || split[1].equals("vertical")) { + Region region = session.getRegion(); + int oldSize = region.getSize(); + region.expand(new Vector(0, 128, 0)); + region.expand(new Vector(0, -128, 0)); + session.learnRegionChanges(); + int newSize = region.getSize(); + player.print("Region expanded " + (newSize - oldSize) + " blocks [top-to-bottom]."); + return true; + } + int change = Integer.parseInt(split[1]); + int reverseChange = 0; + if (split.length == 3) { - dir = getDirection(player, split[2].toLowerCase()); + try { + reverseChange = Integer.parseInt(split[2]) * -1; + dir = getDirection(player, "me"); + } catch (NumberFormatException e) { + dir = getDirection(player, split[2].toLowerCase()); + } + } else if (split.length == 4) { + reverseChange = Integer.parseInt(split[2]) * -1; + dir = getDirection(player, split[3].toLowerCase()); } else { dir = getDirection(player, "me"); } @@ -1293,6 +1302,9 @@ public class WorldEditController { Region region = session.getRegion(); int oldSize = region.getSize(); region.expand(dir.multiply(change)); + if (reverseChange != 0) { + region.expand(dir.multiply(reverseChange)); + } session.learnRegionChanges(); int newSize = region.getSize(); player.print("Region expanded " + (newSize - oldSize) + " blocks."); @@ -1301,11 +1313,20 @@ public class WorldEditController { // Contract } else if (split[0].equalsIgnoreCase("//contract")) { - checkArgs(split, 1, 2, split[0]); + checkArgs(split, 1, 3, split[0]); Vector dir; int change = Integer.parseInt(split[1]); + int reverseChange = 0; if (split.length == 3) { - dir = getDirection(player, split[2].toLowerCase()); + try { + reverseChange = Integer.parseInt(split[2]) * -1; + dir = getDirection(player, "me"); + } catch (NumberFormatException e) { + dir = getDirection(player, split[2].toLowerCase()); + } + } else if (split.length == 4) { + reverseChange = Integer.parseInt(split[2]) * -1; + dir = getDirection(player, split[3].toLowerCase()); } else { dir = getDirection(player, "me"); } @@ -1313,6 +1334,9 @@ public class WorldEditController { Region region = session.getRegion(); int oldSize = region.getSize(); region.contract(dir.multiply(change)); + if (reverseChange != 0) { + region.contract(dir.multiply(reverseChange)); + } session.learnRegionChanges(); int newSize = region.getSize(); player.print("Region contracted " + (oldSize - newSize) + " blocks."); @@ -1972,14 +1996,18 @@ public class WorldEditController { if (command.equalsIgnoreCase("/pos1") || command.equalsIgnoreCase("/pos2") || command.equalsIgnoreCase("/hpos1") - || command.equalsIgnoreCase("/hpos2")) { + || command.equalsIgnoreCase("/hpos2") + || command.equalsIgnoreCase("/chunk") + || command.equalsIgnoreCase("/expand") + || command.equalsIgnoreCase("/contract") + || command.equalsIgnoreCase("/shift") + || command.equalsIgnoreCase("toggleeditwand")) { return player.hasPermission(command) || player.hasPermission("worldeditselect") || player.hasPermission("worldedit"); } - return player.hasPermission(command.replace("air", "")) - || player.hasPermission("worldedit"); + return player.hasPermission("worldedit"); } /** From c0f5ab937501398e9e9fe2d97f58aadf1342937d Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 12:17:46 -0800 Subject: [PATCH 12/13] Updated for 2.6. --- CHANGELOG.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 362d9f9de..8b0105dff 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,18 @@ +2.6: +- Removed 'air' prefix from commands. Now //pasteair is just //paste, + //moveair is just //move, etc. +- Made /worldeditselect permission more encompassing, now including //chunk, + //expand, and //contract. +- Added syntax for //expand which allows + you to expand in two directions at once. This also works for //contract. +- Added //expand vert|vertical to expand the selection from top to bottom. +- Added /thaw to reverse /snow. +- Fixed WorldEdit not handling ice removal well. +- Fixed some inaccuracy problems regarding player positions caused by a + recent update. +- Fixed the tree generator. +- Code reorganized a little more. + 2.5.1: - Fixed the WorldEdit bridge used by CraftBook and other plugins. - Fixed issues with permissions where the only reliable permission was From 294e9f92c3d5ece212b556a2a3c4f32c95680109 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 8 Jan 2011 12:20:01 -0800 Subject: [PATCH 13/13] Changed worldedit.updatr to point to cloud.github.com. --- worldedit.updatr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit.updatr b/worldedit.updatr index c3e5d525b..8eee786d6 100644 --- a/worldedit.updatr +++ b/worldedit.updatr @@ -1,5 +1,5 @@ name = WorldEdit version = %version% url = updatr.update.sk89q.com/worldedit.updatr -file = github.com/downloads/sk89q/worldedit/worldedit-%version%.zip +file = cloud.github.com/downloads/sk89q/worldedit/worldedit-%version%.zip notes = \ No newline at end of file