diff --git a/src/HMConfiguration.java b/src/HMConfiguration.java new file mode 100644 index 000000000..44ff7b200 --- /dev/null +++ b/src/HMConfiguration.java @@ -0,0 +1,122 @@ +// $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.io.IOException; +import java.util.HashSet; +import java.util.logging.FileHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.sk89q.util.StringUtil; +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LogFormat; +import com.sk89q.worldedit.snapshots.SnapshotRepository; + +/** + * Configuration for hMod. + * + * @author sk89q + */ +public class HMConfiguration extends LocalConfiguration { + /** + * Logger. + */ + private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); + + /** + * Properties file. + */ + private PropertiesFile properties; + + /** + * Construct the object. + */ + public HMConfiguration() { + properties = new PropertiesFile("worldedit.properties"); + } + + /** + * Loads the configuration. + */ + public void load() { + try { + properties.load(); + } catch (IOException e) { + logger.warning("worldedit.properties could not be loaded: " + + e.getMessage()); + } + + profile = properties.getBoolean("debug-profile", profile); + wandItem = properties.getInt("wand-item", wandItem); + defaultChangeLimit = Math.max(-1, properties.getInt( + "default-max-blocks-changed", defaultChangeLimit)); + maxChangeLimit = Math.max(-1, + properties.getInt("max-blocks-changed", maxChangeLimit)); + maxRadius = Math.max(-1, properties.getInt("max-radius", maxRadius)); + maxSuperPickaxeSize = Math.max(1, properties.getInt( + "max-super-pickaxe-size", maxSuperPickaxeSize)); + registerHelp = properties.getBoolean("register-help", registerHelp); + logComands = properties.getBoolean("log-commands", logComands); + superPickaxeDrop = properties.getBoolean("super-pickaxe-drop-items", + superPickaxeDrop); + superPickaxeManyDrop = properties.getBoolean( + "super-pickaxe-many-drop-items", superPickaxeManyDrop); + noDoubleSlash = properties.getBoolean("no-double-slash", noDoubleSlash); + useInventory = properties.getBoolean("use-inventory", useInventory); + useInventoryOverride = properties.getBoolean("use-inventory-override", + useInventoryOverride); + + // Get disallowed blocks + disallowedBlocks = new HashSet(); + String defdisallowedBlocks = StringUtil.joinString(defaultDisallowedBlocks, ",", 0); + for (String b : properties.getString("disallowed-blocks", + defdisallowedBlocks).split(",")) { + try { + disallowedBlocks.add(Integer.parseInt(b)); + } catch (NumberFormatException e) { + } + } + + String snapshotsDir = properties.getString("snapshots-dir", ""); + if (!snapshotsDir.trim().equals("")) { + snapshotRepo = new SnapshotRepository(snapshotsDir); + } else { + snapshotRepo = null; + } + + String type = properties.getString("shell-save-type", "").trim(); + shellSaveType = type.equals("") ? null : type; + + String logFile = properties.getString("log-file", ""); + if (!logFile.equals("")) { + try { + FileHandler handler = new FileHandler(logFile, true); + handler.setFormatter(new LogFormat()); + logger.addHandler(handler); + } catch (IOException e) { + logger.log(Level.WARNING, "Could not use log file " + logFile + ": " + + e.getMessage()); + } + } else { + for (Handler handler : logger.getHandlers()) { + logger.removeHandler(handler); + } + } + } +} diff --git a/src/HMServerInterface.java b/src/HMServerInterface.java index 9d0478e4c..c10ded3d7 100644 --- a/src/HMServerInterface.java +++ b/src/HMServerInterface.java @@ -340,7 +340,7 @@ public class HMServerInterface extends ServerInterface { */ public void simulateBlockMine(LocalWorld world, Vector pt) { int type = getBlockType(world, pt); - setBlockType(world, pt, 0); + //setBlockType(world, pt, 0); if (type == 1) { dropItem(world, pt, 4); } // Stone else if (type == 2) { dropItem(world, pt, 3); } // Grass diff --git a/src/HMWorldEditListener.java b/src/HMWorldEditListener.java index bf4106372..91a9f57a1 100755 --- a/src/HMWorldEditListener.java +++ b/src/HMWorldEditListener.java @@ -18,14 +18,7 @@ */ import java.util.Map; -import java.util.HashSet; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.logging.Handler; -import java.util.logging.FileHandler; -import java.io.*; import com.sk89q.worldedit.*; -import com.sk89q.worldedit.snapshots.*; /** * The event listener for WorldEdit in hMod. @@ -33,18 +26,14 @@ import com.sk89q.worldedit.snapshots.*; * @author sk89q */ public class HMWorldEditListener extends PluginListener { - /** - * Logger. - */ - private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); - /** - * Properties file. - */ - private PropertiesFile properties; /** * Main WorldEdit controller. */ private WorldEditController controller; + /** + * Configuration. + */ + private LocalConfiguration config; /** * A copy of the server instance. This is where all world<->WorldEdit calls * will go through. @@ -58,6 +47,9 @@ public class HMWorldEditListener extends PluginListener { */ public HMWorldEditListener(ServerInterface server) { this.server = server; + + config = new HMConfiguration(); + controller = new WorldEditController(server, config); } /** @@ -94,7 +86,7 @@ public class HMWorldEditListener extends PluginListener { Vector pos = new Vector(blockClicked.getX(), blockClicked.getY(), blockClicked.getZ()); - return controller.handleBlockRightClick(wrapPlayer(player), pos); + return controller.handleBlockRightClick(wrapPlayer(player), null, pos); } /** @@ -110,7 +102,7 @@ public class HMWorldEditListener extends PluginListener { Vector pos = new Vector(blockClicked.getX(), blockClicked.getY(), blockClicked.getZ()); - return controller.handleBlockLeftClick(wrapPlayer(player), pos); + return controller.handleBlockLeftClick(wrapPlayer(player), null, pos); } /** @@ -128,74 +120,14 @@ public class HMWorldEditListener extends PluginListener { * Loads the configuration. */ public void loadConfiguration() { - if (properties == null) { - properties = new PropertiesFile("worldedit.properties"); - } else { - try { - properties.load(); - } catch (IOException e) { - logger.warning("worldedit.properties could not be loaded: " - + e.getMessage()); - } - } - - controller.profile = properties.getBoolean("debug-profile", false); - controller.wandItem = properties.getInt("wand-item", 271); - controller.defaultChangeLimit = Math.max(-1, properties.getInt("default-max-blocks-changed", -1)); - controller.maxChangeLimit = Math.max(-1, properties.getInt("max-blocks-changed", -1)); - controller.maxRadius = Math.max(-1, properties.getInt("max-radius", -1)); - controller.maxSuperPickaxeSize = Math.max(1, properties.getInt("max-super-pickaxe-size", 5)); - controller.registerHelp = properties.getBoolean("register-help", true); - controller.logComands = properties.getBoolean("log-commands", false); - controller.superPickaxeDrop = properties.getBoolean("super-pickaxe-drop-items", true); - controller.superPickaxeManyDrop = properties.getBoolean("super-pickaxe-many-drop-items", false); - controller.noDoubleSlash = properties.getBoolean("no-double-slash", false); - controller.useInventory = properties.getBoolean("use-inventory", false); - controller.useInventoryOverride = properties.getBoolean("use-inventory-override", false); - - // Get allowed blocks - controller.allowedBlocks = new HashSet(); - for (String b : properties.getString("allowed-blocks", - WorldEditController.getDefaultAllowedBlocks()).split(",")) { - try { - controller.allowedBlocks.add(Integer.parseInt(b)); - } catch (NumberFormatException e) { - } - } - - - String snapshotsDir = properties.getString("snapshots-dir", ""); - if (!snapshotsDir.trim().equals("")) { - controller.snapshotRepo = new SnapshotRepository(snapshotsDir); - } else { - controller.snapshotRepo = null; - } - - String type = properties.getString("shell-save-type", "").trim(); - controller.shellSaveType = type.equals("") ? null : type; - - String logFile = properties.getString("log-file", ""); - if (!logFile.equals("")) { - try { - FileHandler handler = new FileHandler(logFile, true); - handler.setFormatter(new LogFormat()); - logger.addHandler(handler); - } catch (IOException e) { - logger.log(Level.WARNING, "Could not use log file " + logFile + ": " - + e.getMessage()); - } - } else { - for (Handler handler : logger.getHandlers()) { - logger.removeHandler(handler); - } - } + config.load(); } /** * Register commands with help. */ public void registerCommands() { - if (controller.registerHelp) { + if (config.registerHelp) { for (Map.Entry entry : controller.getCommands().entrySet()) { etc.getInstance().addCommand(entry.getKey(), entry.getValue()); } @@ -228,6 +160,12 @@ public class HMWorldEditListener extends PluginListener { return controller.getBridgeSession(wrapPlayer(player)); } + /** + * Wrap a hMod player for WorldEdit. + * + * @param player + * @return + */ private LocalPlayer wrapPlayer(Player player) { return new HMPlayer(server, player); } diff --git a/src/WorldEdit.java b/src/WorldEdit.java index bf6cb8ed8..1b202847c 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -20,8 +20,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.sk89q.worldedit.ServerInterface; - /** * Entry point for the plugin for hey0's mod. * diff --git a/src/com/sk89q/util/StringUtil.java b/src/com/sk89q/util/StringUtil.java new file mode 100644 index 000000000..383542623 --- /dev/null +++ b/src/com/sk89q/util/StringUtil.java @@ -0,0 +1,101 @@ +// $Id$ +/* + * 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 . +*/ + +package com.sk89q.util; + +/** + * String utilities. + * + * @author sk89q + */ +public class StringUtil { + /** + * Trim a string if it is longer than a certain length. + * + * @param str + * @param len + * @return + */ + public static String trimLength(String str, int len) { + if (str.length() > len) { + return str.substring(0, len); + } + + return str; + } + + /** + * Join an array of strings into a string. + * + * @param str + * @param delimiter + * @param initialIndex + * @return + */ + public static String joinString(String[] str, String delimiter, + int initialIndex) { + if (str.length == 0) { + return ""; + } + StringBuilder buffer = new StringBuilder(str[initialIndex]); + for (int i = initialIndex + 1; i < str.length; i++) { + buffer.append(delimiter).append(str[i]); + } + return buffer.toString(); + } + + /** + * Join an array of strings into a string. + * + * @param str + * @param delimiter + * @param initialIndex + * @return + */ + public static String joinString(Object[] str, String delimiter, + int initialIndex) { + if (str.length == 0) { + return ""; + } + StringBuilder buffer = new StringBuilder(str[initialIndex].toString()); + for (int i = initialIndex + 1; i < str.length; i++) { + buffer.append(delimiter).append(str[i].toString()); + } + return buffer.toString(); + } + + /** + * Join an array of strings into a string. + * + * @param str + * @param delimiter + * @param initialIndex + * @return + */ + public static String joinString(int[] str, String delimiter, + int initialIndex) { + if (str.length == 0) { + return ""; + } + StringBuilder buffer = new StringBuilder(Integer.toString(str[initialIndex])); + for (int i = initialIndex + 1; i < str.length; i++) { + buffer.append(delimiter).append(Integer.toString(str[i])); + } + return buffer.toString(); + } +} diff --git a/src/com/sk89q/worldedit/CuboidClipboard.java b/src/com/sk89q/worldedit/CuboidClipboard.java index 71a210ed2..c1664ab54 100644 --- a/src/com/sk89q/worldedit/CuboidClipboard.java +++ b/src/com/sk89q/worldedit/CuboidClipboard.java @@ -1,4 +1,3 @@ -package com.sk89q.worldedit; // $Id$ /* * WorldEdit @@ -18,7 +17,8 @@ package com.sk89q.worldedit; * along with this program. If not, see . */ -import com.sk89q.worldedit.*; +package com.sk89q.worldedit; + import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.data.*; import org.jnbt.*; diff --git a/src/com/sk89q/worldedit/LocalConfiguration.java b/src/com/sk89q/worldedit/LocalConfiguration.java new file mode 100644 index 000000000..beb29d238 --- /dev/null +++ b/src/com/sk89q/worldedit/LocalConfiguration.java @@ -0,0 +1,59 @@ +// $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 . +*/ + +package com.sk89q.worldedit; + +import java.util.Set; + +import com.sk89q.worldedit.snapshots.SnapshotRepository; + +/** + * Represents WorldEdit's configuration. + * + * @author sk89q + */ +public abstract class LocalConfiguration { + protected static final int[] defaultDisallowedBlocks = new int[] { + 6, 7, 14, 15, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 39, 31, + 32, 33, 34, 36, 37, 38, 39, 40, 46, 50, 51, 56, 59, 69, 73, 74, + 75, 76, 77, 81, 83 + }; + + public boolean profile = false; + public Set disallowedBlocks = null; + public int defaultChangeLimit = -1; + public int maxChangeLimit = -1; + public String shellSaveType = null; + public SnapshotRepository snapshotRepo = null; + public int maxRadius = -1; + public int maxSuperPickaxeSize = 5; + public boolean logComands = false; + public boolean registerHelp = true; + public int wandItem = 271; + public boolean superPickaxeDrop = true; + public boolean superPickaxeManyDrop = true; + public boolean noDoubleSlash = false; + public boolean useInventory = false; + public boolean useInventoryOverride = false; + + /** + * Loads the configuration. + */ + public abstract void load(); +} diff --git a/src/com/sk89q/worldedit/LocalPlayer.java b/src/com/sk89q/worldedit/LocalPlayer.java index ab5618e2b..621cad592 100644 --- a/src/com/sk89q/worldedit/LocalPlayer.java +++ b/src/com/sk89q/worldedit/LocalPlayer.java @@ -477,6 +477,15 @@ public abstract class LocalPlayer { * @return */ public abstract boolean hasPermission(String perm); + + /** + * Returns true if the player can destroy bedrock. + * + * @return + */ + public boolean canDestroyBedrock() { + return hasPermission("worldeditbedrock"); + } /** * Returns true if equal. diff --git a/src/com/sk89q/worldedit/LocalSession.java b/src/com/sk89q/worldedit/LocalSession.java index cd1a85501..77843a379 100644 --- a/src/com/sk89q/worldedit/LocalSession.java +++ b/src/com/sk89q/worldedit/LocalSession.java @@ -21,6 +21,8 @@ package com.sk89q.worldedit; import java.util.LinkedList; import com.sk89q.worldedit.snapshots.Snapshot; +import com.sk89q.worldedit.superpickaxe.SinglePickaxe; +import com.sk89q.worldedit.superpickaxe.SuperPickaxeMode; import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.CuboidRegion; @@ -30,24 +32,8 @@ import com.sk89q.worldedit.regions.CuboidRegion; * @author sk89q */ public class LocalSession { - /** - * List of super pick axe modes. - */ - public static enum SuperPickaxeMode { - SINGLE, - SAME_TYPE_RECURSIVE, - SAME_TYPE_AREA - }; - /** - * List of tools. - */ - public static enum Tool { - NONE, - INFO, - TREE, - } - public static final int MAX_HISTORY_SIZE = 15; + private boolean placeAtPos1 = false; private Vector pos1, pos2; private Region region; @@ -55,10 +41,9 @@ public class LocalSession { private int historyPointer = 0; private CuboidClipboard clipboard; private boolean toolControl = true; - private boolean superPickAxe = false; - private SuperPickaxeMode superPickaxeMode = SuperPickaxeMode.SINGLE; - private Tool tool = Tool.NONE; - private int superPickaxeRange = 3; + private boolean superPickaxe = false; + private SuperPickaxeMode superPickaxeMode = new SinglePickaxe(); + private SuperPickaxeMode tool; private int maxBlocksChanged = -1; private boolean useInventory; private Snapshot snapshot; @@ -291,25 +276,25 @@ public class LocalSession { * @return status */ public boolean hasSuperPickAxe() { - return superPickAxe; + return superPickaxe; } /** * Enable super pick axe. * - * @param superPickAxe + * @param superPickaxe */ public void enableSuperPickAxe() { - superPickAxe = true; + superPickaxe = true; } /** * Disable super pick axe. * - * @param superPickAxe + * @param superPickaxe */ public void disableSuperPickAxe() { - superPickAxe = false; + superPickaxe = false; } /** @@ -318,8 +303,8 @@ public class LocalSession { * @return status */ public boolean toggleSuperPickAxe() { - superPickAxe = !superPickAxe; - return superPickAxe; + superPickaxe = !superPickaxe; + return superPickaxe; } /** @@ -385,31 +370,17 @@ public class LocalSession { this.superPickaxeMode = superPickaxeMode; } - /** - * @return the superPickaxeRange - */ - public int getSuperPickaxeRange() { - return superPickaxeRange; - } - - /** - * @param superPickaxeRange the superPickaxeRange to set - */ - public void setSuperPickaxeRange(int superPickaxeRange) { - this.superPickaxeRange = superPickaxeRange; - } - /** * @return the tool */ - public Tool getTool() { + public SuperPickaxeMode getTool() { return tool; } /** * @param tool the tool to set */ - public void setTool(Tool tool) { + public void setTool(SuperPickaxeMode tool) { this.tool = tool; } diff --git a/src/com/sk89q/worldedit/WorldEditController.java b/src/com/sk89q/worldedit/WorldEditController.java index 6ca46ca4f..306d2ce5c 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -32,6 +32,7 @@ import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.data.*; import com.sk89q.worldedit.filters.*; import com.sk89q.worldedit.snapshots.*; +import com.sk89q.worldedit.superpickaxe.*; import com.sk89q.worldedit.regions.*; import com.sk89q.worldedit.patterns.*; @@ -59,6 +60,10 @@ public class WorldEditController { * Server interface. */ private ServerInterface server; + /** + * WorldEdit configuration. + */ + private LocalConfiguration config; /** * Stores a list of WorldEdit sessions, keyed by players' names. Sessions @@ -76,31 +81,16 @@ public class WorldEditController { * will be loaded into help. On unload, they will be removed. */ private HashMap commands = new HashMap(); - - public boolean profile; - public HashSet allowedBlocks; - public int defaultChangeLimit = -1; - public int maxChangeLimit = -1; - public String shellSaveType; - public SnapshotRepository snapshotRepo; - public int maxRadius = -1; - public int maxSuperPickaxeSize = 5; - public boolean logComands = false; - public boolean registerHelp = true; - public int wandItem = 271; - public boolean superPickaxeDrop = true; - public boolean superPickaxeManyDrop = true; - public boolean noDoubleSlash = false; - public boolean useInventory = false; - public boolean useInventoryOverride = false; - + /** * Construct an instance of the plugin * * @param server + * @param config */ - public WorldEditController(ServerInterface server) { + public WorldEditController(ServerInterface server, LocalConfiguration config) { this.server = server; + this.config = config; // Note: Commands should only have the phrase 'air' at the end // for now (see SMWorldEditListener.canUseCommand) @@ -143,8 +133,12 @@ public class WorldEditController { commands.put("//fillr", "[ID] [Radius] - Fill a hole fully recursively"); commands.put("//drain", "[Radius] - Drain nearby water/lava pools"); commands.put("//limit", "[Num] - See documentation"); - commands.put("//mode", "[Mode] - Set super pickaxe mode (single/recursive/area)"); - commands.put("//tool", "[Tool] - Set pickaxe tool (none/tree/info)"); + commands.put("/single", "Switch to single block super pickaxe mode"); + commands.put("/area", "[Range] - Switch to area super pickaxe mode"); + commands.put("/recur", "[Range] - Switch to recursive super pickaxe mode"); + commands.put("/none", "Switch to no tool"); + commands.put("/info", "Switch to the info tool"); + commands.put("/tree", "Switch to the tree tool"); commands.put("//expand", "[Num] - Expands the selection"); commands.put("//contract", "[Num] - Contracts the selection"); commands.put("//shift", "[Num] - Shift the selection"); @@ -179,7 +173,7 @@ public class WorldEditController { } /** - * Gets the WorldEditLibrary session for a player. + * Gets the WorldEdit session for a player. * * @param player * @return @@ -187,27 +181,41 @@ public class WorldEditController { public LocalSession getSession(LocalPlayer player) { if (sessions.containsKey(player)) { return sessions.get(player); - } else { - LocalSession session = new LocalSession(); - if (!player.hasPermission("/worldeditnomax") - && maxChangeLimit > -1) { - if (defaultChangeLimit < 0) { - // No infinite! - session.setBlockChangeLimit(maxChangeLimit); - } else { - // Bound - session.setBlockChangeLimit( - Math.min(defaultChangeLimit, maxChangeLimit)); - } - } else { - session.setBlockChangeLimit(defaultChangeLimit); - } - session.setUseInventory(useInventory - && (!useInventoryOverride - || !player.hasPermission("/worldeditunlimited"))); - sessions.put(player, session); - return session; } + + LocalSession session = new LocalSession(); + + // Set the limit on the number of blocks that an operation can + // change at once, or don't if the player has an override or there + // is no limit. There is also a default limit + if (!player.hasPermission("worldeditnomax") + && config.maxChangeLimit > -1) { + + // If the default limit is infinite but there is a maximum + // limit, make sure to not have it be overridden + if (config.defaultChangeLimit < 0) { + session.setBlockChangeLimit(config.maxChangeLimit); + } else { + // Bound the change limit + int limit = Math.min(config.defaultChangeLimit, + config.maxChangeLimit); + session.setBlockChangeLimit(limit); + } + } else { + // No change limit or override + session.setBlockChangeLimit(config.defaultChangeLimit); + } + + // Have the session use inventory if it's enabled and the player + // doesn't have an override + session.setUseInventory(config.useInventory + && (!config.useInventoryOverride + || !player.hasPermission("worldeditunlimited"))); + + // Remember the session + sessions.put(player, session); + + return session; } /** @@ -223,12 +231,14 @@ public class WorldEditController { /** * Get an item ID from an item name or an item ID number. * + * @param player * @param arg + * @param allAllowed true to ignore blacklists * @return * @throws UnknownItemException * @throws DisallowedItemException */ - public BaseBlock getBlock(String arg, boolean allAllowed) + public BaseBlock getBlock(LocalPlayer player, String arg, boolean allAllowed) throws UnknownItemException, DisallowedItemException { BlockType blockType; arg = arg.replace("_", " "); @@ -239,6 +249,7 @@ public class WorldEditController { int data; + // Parse the block data (optional) try { data = args1.length > 1 ? Integer.parseInt(args1[1]) : 0; if (data > 15 || data < 0) { @@ -248,6 +259,8 @@ public class WorldEditController { data = 0; } + // Attempt to parse the item ID or otherwise resolve an item/block + // name to its numeric ID try { blockType = BlockType.fromID(Integer.parseInt(testID)); } catch (NumberFormatException e) { @@ -265,8 +278,10 @@ public class WorldEditController { } // Check if the item is allowed - if (allAllowed || allowedBlocks.isEmpty() - || allowedBlocks.contains(blockType.getID())) { + if (allAllowed || player.hasPermission("worldeditanyblock") + || !config.disallowedBlocks.contains(blockType.getID())) { + + // Allow special sign text syntax if (blockType == BlockType.SIGN_POST || blockType == BlockType.WALL_SIGN) { String[] text = new String[4]; @@ -275,6 +290,8 @@ public class WorldEditController { text[2] = args0.length > 3 ? args0[3] : ""; text[3] = args0.length > 4 ? args0[4] : ""; return new SignBlock(blockType.getID(), data, text); + + // Alow setting mob spawn type } else if (blockType == BlockType.MOB_SPAWNER) { if (args0.length > 1) { if (!server.isValidMobType(args0[1])) { @@ -295,29 +312,31 @@ public class WorldEditController { /** * Get a block. * + * @param player * @param id * @return * @throws UnknownItemException * @throws DisallowedItemException */ - public BaseBlock getBlock(String id) throws UnknownItemException, - DisallowedItemException { - return getBlock(id, false); + public BaseBlock getBlock(LocalPlayer player, String id) + throws UnknownItemException, DisallowedItemException { + return getBlock(player, id, false); } /** * Get a list of blocks as a set. This returns a Pattern. * + * @param player * @param list * @return pattern */ - public Pattern getBlockPattern(String list) + public Pattern getBlockPattern(LocalPlayer player, String list) throws UnknownItemException, DisallowedItemException { String[] items = list.split(","); if (items.length == 1) { - return new SingleBlockPattern(getBlock(items[0])); + return new SingleBlockPattern(getBlock(player, items[0])); } List blockChances = new ArrayList(); @@ -329,10 +348,10 @@ public class WorldEditController { if (s.matches("[0-9]+(?:\\.(?:[0-9]+)?)?%.*")) { String[] p = s.split("%"); chance = Double.parseDouble(p[0]); - block = getBlock(p[1]); + block = getBlock(player, p[1]); } else { chance = 1; - block = getBlock(s); + block = getBlock(player, s); } blockChances.add(new BlockChance(block, chance)); @@ -344,16 +363,19 @@ public class WorldEditController { /** * Get a list of blocks as a set. * + *@param player * @param list - * @params allBlocksAllowed + * @param allBlocksAllowed * @return set */ - public Set getBlockIDs(String list, boolean allBlocksAllowed) + public Set getBlockIDs(LocalPlayer player, + String list, boolean allBlocksAllowed) throws UnknownItemException, DisallowedItemException { + String[] items = list.split(","); Set blocks = new HashSet(); for (String s : items) { - blocks.add(getBlock(s, allBlocksAllowed).getID()); + blocks.add(getBlock(player, s, allBlocksAllowed).getID()); } return blocks; } @@ -386,7 +408,7 @@ public class WorldEditController { * @throws MaxRadiusException */ private void checkMaxRadius(int radius) throws MaxRadiusException { - if (maxRadius > 0 && radius > maxRadius) { + if (config.maxRadius > 0 && radius > config.maxRadius) { throw new MaxRadiusException(); } } @@ -409,7 +431,7 @@ public class WorldEditController { LocalSession session, EditSession editSession, String[] split) throws WorldEditException { - if (logComands) { + if (config.logComands) { logger.log(Level.INFO, "WorldEdit: " + player.getName() + ": " + joinString(split, " ")); } @@ -565,7 +587,7 @@ public class WorldEditController { // Edit wand } else if (split[0].equalsIgnoreCase("//wand")) { checkArgs(split, 0, 0, split[0]); - player.giveItem(wandItem, 1); + player.giveItem(config.wandItem, 1); player.print("Left click: select pos #1; Right click: select pos #2"); return true; @@ -604,10 +626,11 @@ public class WorldEditController { } else if (split[0].equalsIgnoreCase("//limit")) { checkArgs(split, 1, 1, split[0]); int limit = Math.max(-1, Integer.parseInt(split[1])); - if (!player.hasPermission("/worldeditnomax") - && maxChangeLimit > -1) { - if (limit > maxChangeLimit) { - player.printError("Your maximum allowable limit is " + maxChangeLimit + "."); + if (!player.hasPermission("worldeditnomax") + && config.maxChangeLimit > -1) { + if (limit > config.maxChangeLimit) { + player.printError("Your maximum allowable limit is " + + config.maxChangeLimit + "."); return true; } } @@ -617,61 +640,63 @@ public class WorldEditController { return true; - // Set super pick axe mode - } else if (split[0].equalsIgnoreCase("//mode")) { - checkArgs(split, 1, 2, split[0]); - - if (split[1].equalsIgnoreCase("single")) { - session.setSuperPickaxeMode(LocalSession.SuperPickaxeMode.SINGLE); - player.print("Mode set to single block."); - } else if (split[1].equalsIgnoreCase("recursive") - || split[1].equalsIgnoreCase("area")) { - if (split.length == 3) { - int size = Math.max(1, Integer.parseInt(split[2])); - if (size <= maxSuperPickaxeSize) { - LocalSession.SuperPickaxeMode mode = - split[1].equalsIgnoreCase("recursive") ? - LocalSession.SuperPickaxeMode.SAME_TYPE_RECURSIVE : - LocalSession.SuperPickaxeMode.SAME_TYPE_AREA; - session.setSuperPickaxeMode(mode); - session.setSuperPickaxeRange(size); - player.print("Mode set to " + split[1].toLowerCase() + "."); - } else { - player.printError("Max size is " + maxSuperPickaxeSize + "."); - } - } else { - player.printError("Size argument required for mode " - + split[1].toLowerCase() + "."); - } - } else { - player.printError("Unknown super pick axe mode."); + // Single super pickaxe mode + } else if (split[0].equalsIgnoreCase("/single")) { + if (!canUseCommand(player, "//")) { + player.printError("You don't have permission for super pickaxe usage."); + return true; } + + checkArgs(split, 0, 0, split[0]); + session.setSuperPickaxeMode(new SinglePickaxe()); + session.enableSuperPickAxe(); + player.print("Mode changed. Left click with a pickaxe. // to disable."); return true; - // Set tool - } else if (split[0].equalsIgnoreCase("//tool")) { - checkArgs(split, 1, 1, split[0]); - - if (split[1].equalsIgnoreCase("none")) { - session.setTool(LocalSession.Tool.NONE); - player.print("No tool equipped. -3 XP, +10 Manliness"); - } else if (split[1].equalsIgnoreCase("tree")) { - if (!canUseCommand(player, "/treetool")) { - player.printError("You do not have the /treetool permission."); - return true; - } - session.setTool(LocalSession.Tool.TREE); - player.print("Tree planting tool equipped. +5 XP"); - } else if (split[1].equalsIgnoreCase("info")) { - if (!canUseCommand(player, "/infotool")) { - player.printError("You do not have the /infotool permission."); - return true; - } - session.setTool(LocalSession.Tool.INFO); - player.print("Block information tool equipped."); - } else { - player.printError("Unknown tool."); + // Area/recursive super pickaxe mode + } else if (split[0].equalsIgnoreCase("/area") + || split[0].equalsIgnoreCase("/recur")) { + + if (!canUseCommand(player, "//")) { + player.printError("You don't have permission for super pickaxe usage."); + return true; } + + checkArgs(split, 1, 1, split[0]); + + boolean recur = split[0].equalsIgnoreCase("/recur"); + int range = Integer.parseInt(split[1]); + + if (range > config.maxSuperPickaxeSize) { + player.printError("Maximum range: " + config.maxSuperPickaxeSize); + return true; + } + + session.setSuperPickaxeMode( + recur ? new RecursivePickaxe(range) : new AreaPickaxe(range)); + session.enableSuperPickAxe(); + player.print("Mode changed. Left click with a pickaxe. // to disable."); + return true; + + // Tree tool + } else if (split[0].equalsIgnoreCase("/tree")) { + checkArgs(split, 0, 0, split[0]); + session.setTool(new TreePlanter()); + player.print("Tree tool equipped. Right click with a pickaxe."); + return true; + + // Info tool + } else if (split[0].equalsIgnoreCase("/info")) { + checkArgs(split, 0, 0, split[0]); + session.setTool(new QueryTool()); + player.print("Info tool equipped. Right click with a pickaxe."); + return true; + + // Info tool + } else if (split[0].equalsIgnoreCase("/none")) { + checkArgs(split, 0, 0, split[0]); + session.setTool(null); + player.print("Now no longer equipping a tool."); return true; // Undo @@ -740,7 +765,7 @@ public class WorldEditController { } else if (split[0].equalsIgnoreCase("//hcyl") || split[0].equalsIgnoreCase("//cyl")) { checkArgs(split, 2, 3, split[0]); - BaseBlock block = getBlock(split[1]); + BaseBlock block = getBlock(player, split[1]); int radius = Math.max(1, Integer.parseInt(split[2])); int height = split.length > 3 ? Integer.parseInt(split[3]) : 1; boolean filled = split[0].equalsIgnoreCase("//cyl"); @@ -760,7 +785,7 @@ public class WorldEditController { } else if (split[0].equalsIgnoreCase("//sphere") || split[0].equalsIgnoreCase("//hsphere")) { checkArgs(split, 2, 3, split[0]); - BaseBlock block = getBlock(split[1]); + BaseBlock block = getBlock(player, split[1]); int radius = Math.max(1, Integer.parseInt(split[2])); boolean raised = split.length > 3 ? (split[3].equalsIgnoreCase("true") @@ -784,7 +809,7 @@ public class WorldEditController { || split[0].equalsIgnoreCase("//fillr")) { boolean recursive = split[0].equalsIgnoreCase("//fillr"); checkArgs(split, 2, recursive ? 2 : 3, split[0]); - Pattern pattern = getBlockPattern(split[1]); + Pattern pattern = getBlockPattern(player, split[1]); int radius = Math.max(1, Integer.parseInt(split[2])); checkMaxRadius(radius); int depth = split.length > 3 ? Math.max(1, Integer.parseInt(split[3])) : 1; @@ -831,7 +856,7 @@ public class WorldEditController { // Remove blocks near } else if (split[0].equalsIgnoreCase("/removenear")) { checkArgs(split, 2, 2, split[0]); - BaseBlock block = getBlock(split[1], true); + BaseBlock block = getBlock(player, split[1], true); int size = Math.max(1, Integer.parseInt(split[2])); checkMaxRadius(size); @@ -844,7 +869,7 @@ public class WorldEditController { // Extinguish } else if (split[0].equalsIgnoreCase("/ex")) { checkArgs(split, 0, 1, split[0]); - int defaultRadius = maxRadius != -1 ? Math.min(40, maxRadius) : 40; + int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40; int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : defaultRadius; checkMaxRadius(size); @@ -948,7 +973,7 @@ public class WorldEditController { // Get count } else if (split[0].equalsIgnoreCase("//count")) { checkArgs(split, 1, 1, split[0]); - Set searchIDs = getBlockIDs(split[1], true); + Set searchIDs = getBlockIDs(player, split[1], true); player.print("Counted: " + editSession.countBlocks(session.getRegion(), searchIDs)); return true; @@ -977,7 +1002,7 @@ public class WorldEditController { // Replace all blocks in the region } else if(split[0].equalsIgnoreCase("//set")) { checkArgs(split, 1, 1, split[0]); - Pattern pattern = getBlockPattern(split[1]); + Pattern pattern = getBlockPattern(player, split[1]); int affected; if (pattern instanceof SingleBlockPattern) { affected = editSession.setBlocks(session.getRegion(), @@ -1007,7 +1032,7 @@ public class WorldEditController { // Set the outline of a region } else if(split[0].equalsIgnoreCase("//outline")) { checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); + BaseBlock block = getBlock(player, split[1]); int affected = editSession.makeCuboidFaces(session.getRegion(), block); player.print(affected + " block(s) have been changed."); @@ -1016,7 +1041,7 @@ public class WorldEditController { // Set the walls of a region } else if(split[0].equalsIgnoreCase("//walls")) { checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); + BaseBlock block = getBlock(player, split[1]); int affected = editSession.makeCuboidWalls(session.getRegion(), block); player.print(affected + " block(s) have been changed."); @@ -1063,10 +1088,10 @@ public class WorldEditController { Pattern to; if (split.length == 2) { from = null; - to = getBlockPattern(split[1]); + to = getBlockPattern(player, split[1]); } else { - from = getBlockIDs(split[1], true); - to = getBlockPattern(split[2]); + from = getBlockIDs(player, split[1], true); + to = getBlockPattern(player, split[2]); } int affected = 0; @@ -1088,10 +1113,10 @@ public class WorldEditController { BaseBlock to; if (split.length == 3) { from = null; - to = getBlock(split[2]); + to = getBlock(player, split[2]); } else { - from = getBlockIDs(split[2], true); - to = getBlock(split[3]); + from = getBlockIDs(player, split[2], true); + to = getBlock(player, split[3]); } Vector min = player.getBlockIn().subtract(size, size, size); @@ -1106,7 +1131,7 @@ public class WorldEditController { // Lay blocks over an area } else if (split[0].equalsIgnoreCase("//overlay")) { checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); + BaseBlock block = getBlock(player, split[1]); Region region = session.getRegion(); int affected = editSession.overlayCuboidBlocks(region, block); @@ -1123,7 +1148,7 @@ public class WorldEditController { if (cut) { checkArgs(split, 0, 1, split[0]); if (split.length > 1) { - getBlock(split[1]); + getBlock(player, split[1]); } } else { checkArgs(split, 0, 0, split[0]); @@ -1204,7 +1229,7 @@ public class WorldEditController { // Replacement block argument if (split.length > 3) { - replace = getBlock(split[3]); + replace = getBlock(player, split[3]); } else { replace = new BaseBlock(0); } @@ -1367,9 +1392,9 @@ public class WorldEditController { Set chunks = session.getRegion().getChunks(); FileOutputStream out = null; - if (shellSaveType == null) { + if (config.shellSaveType == null) { player.printError("shell-save-type has to be configured in worldedit.properties"); - } else if (shellSaveType.equalsIgnoreCase("bat")) { + } else if (config.shellSaveType.equalsIgnoreCase("bat")) { try { out = new FileOutputStream("worldedit-delchunks.bat"); OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8"); @@ -1398,7 +1423,7 @@ public class WorldEditController { try { out.close(); } catch (IOException ie) {} } } - } else if (shellSaveType.equalsIgnoreCase("bash")) { + } else if (config.shellSaveType.equalsIgnoreCase("bash")) { try { out = new FileOutputStream("worldedit-delchunks.sh"); OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8"); @@ -1441,8 +1466,8 @@ public class WorldEditController { int num = split.length > 1 ? Math.min(40, Math.max(5, Integer.parseInt(split[1]))) : 5; - if (snapshotRepo != null) { - Snapshot[] snapshots = snapshotRepo.getSnapshots(); + if (config.snapshotRepo != null) { + Snapshot[] snapshots = config.snapshotRepo.getSnapshots(); if (snapshots.length > 0) { for (byte i = 0; i < Math.min(num, snapshots.length); i++) { @@ -1463,7 +1488,7 @@ public class WorldEditController { } else if (split[0].equalsIgnoreCase("//use")) { checkArgs(split, 1, 1, split[0]); - if (snapshotRepo == null) { + if (config.snapshotRepo == null) { player.printError("Snapshot/backup restore is not configured."); return true; } @@ -1472,7 +1497,7 @@ public class WorldEditController { // Want the latest snapshot? if (name.equalsIgnoreCase("latest")) { - Snapshot snapshot = snapshotRepo.getDefaultSnapshot(); + Snapshot snapshot = config.snapshotRepo.getDefaultSnapshot(); if (snapshot != null) { session.setSnapshot(null); @@ -1482,7 +1507,7 @@ public class WorldEditController { } } else { try { - session.setSnapshot(snapshotRepo.getSnapshot(name)); + session.setSnapshot(config.snapshotRepo.getSnapshot(name)); player.print("Snapshot set to: " + name); } catch (InvalidSnapshotException e) { player.printError("That snapshot does not exist or is not available."); @@ -1495,7 +1520,7 @@ public class WorldEditController { } else if (split[0].equalsIgnoreCase("//restore")) { checkArgs(split, 0, 1, split[0]); - if (snapshotRepo == null) { + if (config.snapshotRepo == null) { player.printError("Snapshot/backup restore is not configured."); return true; } @@ -1505,7 +1530,7 @@ public class WorldEditController { if (split.length > 1) { try { - snapshot = snapshotRepo.getSnapshot(split[1]); + snapshot = config.snapshotRepo.getSnapshot(split[1]); } catch (InvalidSnapshotException e) { player.printError("That snapshot does not exist or is not available."); return true; @@ -1518,7 +1543,7 @@ public class WorldEditController { // No snapshot set? if (snapshot == null) { - snapshot = snapshotRepo.getDefaultSnapshot(); + snapshot = config.snapshotRepo.getDefaultSnapshot(); if (snapshot == null) { player.printError("No snapshots were found."); @@ -1707,20 +1732,21 @@ public class WorldEditController { * Called on right click. * * @param player + * @param world * @param clicked * @return false if you want the action to go through */ - @SuppressWarnings("deprecation") - public boolean handleBlockRightClick(LocalPlayer player, Vector clicked) { + public boolean handleBlockRightClick(LocalPlayer player, LocalWorld world, + Vector clicked) { int itemInHand = player.getItemInHand(); // This prevents needless sessions from being created - if (!hasSession(player) && !(itemInHand == wandItem && + if (!hasSession(player) && !(itemInHand == config.wandItem && canUseCommand(player, "//pos2"))) { return false; } LocalSession session = getSession(player); - if (itemInHand == wandItem && session.isToolControlEnabled() + if (itemInHand == config.wandItem && session.isToolControlEnabled() && canUseCommand(player, "//pos2")) { session.setPos2(clicked); try { @@ -1731,36 +1757,9 @@ public class WorldEditController { } return true; - } else if (player.isHoldingPickAxe() - && session.getTool() == LocalSession.Tool.TREE) { - EditSession editSession = - new EditSession(server, player.getWorld(), session.getBlockChangeLimit()); - - try { - if (!server.generateTree(editSession, player.getWorld(), clicked)) { - player.printError("Notch won't let you put a tree there."); - } - } finally { - session.remember(editSession); - } - - return true; - } else if (player.isHoldingPickAxe() - && session.getTool() == LocalSession.Tool.INFO) { - BaseBlock block = (new EditSession(server, player.getWorld(), 0)).rawGetBlock(clicked); - - player.print("\u00A79@" + clicked + ": " + "\u00A7e" - + "Type: " + block.getID() + "\u00A77" + " (" - + BlockType.fromID(block.getID()).getName() + ") " - + "\u00A7f" - + "[" + block.getData() + "]"); - - if (block instanceof MobSpawnerBlock) { - player.printRaw("\u00A7e" + "Mob Type: " - + ((MobSpawnerBlock)block).getMobType()); - } - - return true; + } else if (player.isHoldingPickAxe() && session.getTool() != null) { + return session.getTool().act(server, config, player, session, + world, clicked); } return false; @@ -1770,16 +1769,19 @@ 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, Vector clicked) { + public boolean handleBlockLeftClick(LocalPlayer player, + LocalWorld world, Vector clicked) { + if (!canUseCommand(player, "//pos1") && !canUseCommand(player, "//")) { return false; } LocalSession session = getSession(player); - if (player.getItemInHand() == wandItem) { + if (player.getItemInHand() == config.wandItem) { if (session.isToolControlEnabled()) { // Bug workaround if (clicked.getBlockX() == 0 && clicked.getBlockY() == 0 @@ -1804,119 +1806,16 @@ public class WorldEditController { return true; } - } else if (player.isHoldingPickAxe()) { - if (session.hasSuperPickAxe()) { - boolean canBedrock = canUseCommand(player, "/worldeditbedrock"); - - LocalWorld world = player.getWorld(); - - // Single block super pickaxe - if (session.getSuperPickaxeMode() == - LocalSession.SuperPickaxeMode.SINGLE) { - if (server.getBlockType(world, clicked) == 7 && !canBedrock) { - return true; - } else if (server.getBlockType(world, clicked) == 46) { - return false; - } - - if (superPickaxeDrop) { - server.simulateBlockMine(world, clicked); - } else { - server.setBlockType(world, clicked, 0); - } - - // Area super pickaxe - } else if (session.getSuperPickaxeMode() == - LocalSession.SuperPickaxeMode.SAME_TYPE_AREA) { - int ox = clicked.getBlockX(); - int oy = clicked.getBlockY(); - int oz = clicked.getBlockZ(); - int size = session.getSuperPickaxeRange(); - int initialType = server.getBlockType(world, clicked); - - if (initialType == 7 && !canBedrock) { - return true; - } - - for (int x = ox - size; x <= ox + size; x++) { - for (int y = oy - size; y <= oy + size; y++) { - for (int z = oz - size; z <= oz + size; z++) { - Vector pos = new Vector(x, y, z); - if (server.getBlockType(world, pos) == initialType) { - if (superPickaxeManyDrop) { - server.simulateBlockMine(world, pos); - } else { - server.setBlockType(world, pos, 0); - } - } - } - } - } - - return true; - - // Area super pickaxe - } else if (session.getSuperPickaxeMode() == - LocalSession.SuperPickaxeMode.SAME_TYPE_RECURSIVE) { - int size = session.getSuperPickaxeRange(); - int initialType = server.getBlockType(world, clicked); - - if (initialType == 7 && !canBedrock) { - return true; - } - - recursiveSuperPickaxe(world, clicked.toBlockVector(), clicked, size, - initialType, new HashSet()); - - return true; - } - - return true; + } else if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) { + if (session.getSuperPickaxeMode() != null) { + return session.getSuperPickaxeMode().act(server, config, + player, session, world, clicked); } } return false; } - /** - * Helper method for the recursive super pickaxe. - * - * @param pos - * @param canBedrock - * @return - */ - private void recursiveSuperPickaxe(LocalWorld world, BlockVector pos, Vector origin, - int size, int initialType, Set visited) { - if (origin.distance(pos) > size || visited.contains(pos)) { - return; - } - - visited.add(pos); - - if (server.getBlockType(world, pos) == initialType) { - if (superPickaxeManyDrop) { - server.simulateBlockMine(world, pos); - } else { - server.setBlockType(world, pos, 0); - } - } else { - return; - } - - recursiveSuperPickaxe(world, pos.add(1, 0, 0).toBlockVector(), origin, size, - initialType, visited); - recursiveSuperPickaxe(world, pos.add(-1, 0, 0).toBlockVector(), origin, size, - initialType, visited); - recursiveSuperPickaxe(world, pos.add(0, 0, 1).toBlockVector(), origin, size, - initialType, visited); - recursiveSuperPickaxe(world, pos.add(0, 0, -1).toBlockVector(), origin, size, - initialType, visited); - recursiveSuperPickaxe(world, pos.add(0, 1, 0).toBlockVector(), origin, size, - initialType, visited); - recursiveSuperPickaxe(world, pos.add(0, -1, 0).toBlockVector(), origin, size, - initialType, visited); - } - /** * * @param player @@ -1933,10 +1832,10 @@ public class WorldEditController { String searchCmd = split[0].toLowerCase(); if (commands.containsKey(searchCmd) - || (noDoubleSlash && commands.containsKey("/" + searchCmd)) + || (config.noDoubleSlash && commands.containsKey("/" + searchCmd)) || ((searchCmd.length() < 3 || searchCmd.charAt(2) != '/') && commands.containsKey(searchCmd.substring(1)))) { - if (noDoubleSlash && commands.containsKey("/" + searchCmd)) { + if (config.noDoubleSlash && commands.containsKey("/" + searchCmd)) { split[0] = "/" + split[0]; } else if (commands.containsKey(searchCmd.substring(1))) { split[0] = split[0].substring(1); @@ -1959,9 +1858,9 @@ public class WorldEditController { session.remember(editSession); editSession.flushQueue(); - if (profile) { + if (config.profile) { long time = System.currentTimeMillis() - start; - player.print(( time / 1000.0) + "s elapsed"); + player.print((time / 1000.0) + "s elapsed"); } flushBlockBag(player, editSession); @@ -1984,7 +1883,7 @@ public class WorldEditController { player.printError("Max blocks changed in an operation reached (" + e5.getBlockLimit() + ")."); } catch (MaxRadiusException e) { - player.printError("Maximum radius: " + maxRadius); + player.printError("Maximum radius: " + config.maxRadius); } catch (UnknownDirectionException ue) { player.printError("Unknown direction: " + ue.getDirection()); } catch (InsufficientArgumentsException e6) { @@ -2058,12 +1957,12 @@ public class WorldEditController { || command.equalsIgnoreCase("//hpos1") || command.equalsIgnoreCase("//hpos2")) { return player.hasPermission(command) - || player.hasPermission("/worldeditselect") - || player.hasPermission("/worldedit"); + || player.hasPermission("worldeditselect") + || player.hasPermission("worldedit"); } return player.hasPermission(command.replace("air", "")) - || player.hasPermission("/worldedit"); + || player.hasPermission("worldedit"); } /** @@ -2102,7 +2001,7 @@ public class WorldEditController { return sessions.get(player); } else { LocalSession session = new LocalSession(); - session.setBlockChangeLimit(defaultChangeLimit); + session.setBlockChangeLimit(config.defaultChangeLimit); sessions.put(player, session); return session; } diff --git a/src/com/sk89q/worldedit/superpickaxe/AreaPickaxe.java b/src/com/sk89q/worldedit/superpickaxe/AreaPickaxe.java new file mode 100644 index 000000000..7f3d6fbec --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/AreaPickaxe.java @@ -0,0 +1,82 @@ +// $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 . +*/ + +package com.sk89q.worldedit.superpickaxe; + +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockID; + +/** + * A super pickaxe mode that will remove blocks in an area. + * + * @author sk89q + */ +public class AreaPickaxe implements SuperPickaxeMode { + private static final BaseBlock air = new BaseBlock(0); + private int range; + + public AreaPickaxe(int range) { + this.range = range; + } + + @Override + public boolean act(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, LocalWorld world, + Vector clicked) { + int ox = clicked.getBlockX(); + int oy = clicked.getBlockY(); + int oz = clicked.getBlockZ(); + int initialType = server.getBlockType(world, clicked); + + if (initialType == 0) { + return true; + } + + if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) { + return true; + } + + EditSession editSession = new EditSession(server, world, + session.getBlockChangeLimit()); + + try { + for (int x = ox - range; x <= ox + range; x++) { + 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 (config.superPickaxeManyDrop) { + server.simulateBlockMine(world, pos); + } + + editSession.setBlock(pos, air); + } + } + } + } + } catch (MaxChangedBlocksException e) { + player.printError("Max blocks change limit reached."); + } finally { + session.remember(editSession); + } + + return true; + } +} diff --git a/src/com/sk89q/worldedit/superpickaxe/QueryTool.java b/src/com/sk89q/worldedit/superpickaxe/QueryTool.java new file mode 100644 index 000000000..524c4695f --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/QueryTool.java @@ -0,0 +1,52 @@ +// $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 . +*/ + +package com.sk89q.worldedit.superpickaxe; + +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.*; + +/** + * Plants a tree. + * + * @author sk89q + */ +public class QueryTool implements SuperPickaxeMode { + + @Override + public boolean act(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, LocalWorld world, + Vector clicked) { + BaseBlock block = (new EditSession(server, world, 0)).rawGetBlock(clicked); + + player.print("\u00A79@" + clicked + ": " + "\u00A7e" + + "Type: " + block.getID() + "\u00A77" + " (" + + BlockType.fromID(block.getID()).getName() + ") " + + "\u00A7f" + + "[" + block.getData() + "]"); + + if (block instanceof MobSpawnerBlock) { + player.printRaw("\u00A7e" + "Mob Type: " + + ((MobSpawnerBlock)block).getMobType()); + } + + return true; + } + +} diff --git a/src/com/sk89q/worldedit/superpickaxe/RecursivePickaxe.java b/src/com/sk89q/worldedit/superpickaxe/RecursivePickaxe.java new file mode 100644 index 000000000..077050c68 --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/RecursivePickaxe.java @@ -0,0 +1,119 @@ +// $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 . +*/ + +package com.sk89q.worldedit.superpickaxe; + +import java.util.HashSet; +import java.util.Set; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockID; + +/** + * A pickaxe mode that recursively finds adjacent blocks within range of + * an initial block and of the same type. + * + * @author sk89q + */ +public class RecursivePickaxe implements SuperPickaxeMode { + private static final BaseBlock air = new BaseBlock(0); + private int range; + + public RecursivePickaxe(int range) { + this.range = range; + } + + @Override + public boolean act(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, LocalWorld world, + Vector clicked) { + int initialType = server.getBlockType(world, clicked); + + if (initialType == 0) { + return true; + } + + if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) { + return true; + } + + EditSession editSession = new EditSession(server, world, + session.getBlockChangeLimit()); + + try { + recurse(server, editSession, world, clicked.toBlockVector(), + clicked, range, initialType, new HashSet(), + config.superPickaxeManyDrop); + } catch (MaxChangedBlocksException e) { + player.printError("Max blocks change limit reached."); + } finally { + session.remember(editSession); + } + + return true; + } + + /** + * Helper method. + * + * @param server + * @param superPickaxeManyDrop + * @param world + * @param pos + * @param origin + * @param size + * @param initialType + * @param visited + */ + private void recurse(ServerInterface server, EditSession editSession, + LocalWorld world, BlockVector pos, + Vector origin, int size, int initialType, + Set visited, boolean drop) + throws MaxChangedBlocksException { + + if (origin.distance(pos) > size || visited.contains(pos)) { + return; + } + + visited.add(pos); + + if (editSession.getBlock(pos).getID() == initialType) { + if (drop) { + server.simulateBlockMine(world, pos); + } + editSession.setBlock(pos, air); + } else { + return; + } + + recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(), + origin, size, initialType, visited, drop); + recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(), + origin, size, initialType, visited, drop); + recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(), + origin, size, initialType, visited, drop); + recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(), + origin, size, initialType, visited, drop); + recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(), + origin, size, initialType, visited, drop); + recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(), + origin, size, initialType, visited, drop); + } + +} diff --git a/src/com/sk89q/worldedit/superpickaxe/SinglePickaxe.java b/src/com/sk89q/worldedit/superpickaxe/SinglePickaxe.java new file mode 100644 index 000000000..fe85aa562 --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/SinglePickaxe.java @@ -0,0 +1,52 @@ +// $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 . +*/ + +package com.sk89q.worldedit.superpickaxe; + +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BlockID; + +/** + * A super pickaxe mode that removes one block. + * + * @author sk89q + */ +public class SinglePickaxe implements SuperPickaxeMode { + @Override + public boolean act(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, LocalWorld world, + Vector clicked) { + + if (server.getBlockType(world, clicked) == BlockID.BEDROCK + && !player.canDestroyBedrock()) { + return true; + } else if (server.getBlockType(world, clicked) == BlockID.TNT) { + return false; + } + + if (config.superPickaxeDrop) { + server.simulateBlockMine(world, clicked); + } + + server.setBlockType(world, clicked, 0); + + return true; + } + +} diff --git a/src/com/sk89q/worldedit/superpickaxe/SuperPickaxeMode.java b/src/com/sk89q/worldedit/superpickaxe/SuperPickaxeMode.java new file mode 100644 index 000000000..f8835c549 --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/SuperPickaxeMode.java @@ -0,0 +1,42 @@ +// $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 . +*/ + +package com.sk89q.worldedit.superpickaxe; + +import com.sk89q.worldedit.*; + +/** + * Represents a super pickaxe mode. + * + * @author sk89q + */ +public interface SuperPickaxeMode { + /** + * Perform the action. Should return true to deny the default + * action. + * + * @param player + * @param session + * @param clicked + * @return true to deny + */ + public boolean act(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, LocalWorld world, + Vector clicked); +} diff --git a/src/com/sk89q/worldedit/superpickaxe/TreePlanter.java b/src/com/sk89q/worldedit/superpickaxe/TreePlanter.java new file mode 100644 index 000000000..67a40ce4b --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/TreePlanter.java @@ -0,0 +1,49 @@ +// $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 . +*/ + +package com.sk89q.worldedit.superpickaxe; + +import com.sk89q.worldedit.*; + +/** + * Plants a tree. + * + * @author sk89q + */ +public class TreePlanter implements SuperPickaxeMode { + + @Override + public boolean act(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, LocalWorld world, + Vector clicked) { + EditSession editSession = + new EditSession(server, world, session.getBlockChangeLimit()); + + try { + if (!server.generateTree(editSession, player.getWorld(), clicked)) { + player.printError("Notch won't let you put a tree there."); + } + } finally { + session.remember(editSession); + } + + return true; + } + +}