diff --git a/src/HMConfiguration.java b/src/HMConfiguration.java index 44ff7b200..20a263035 100644 --- a/src/HMConfiguration.java +++ b/src/HMConfiguration.java @@ -81,6 +81,7 @@ public class HMConfiguration extends LocalConfiguration { useInventory = properties.getBoolean("use-inventory", useInventory); useInventoryOverride = properties.getBoolean("use-inventory-override", useInventoryOverride); + maxBrushRadius = properties.getInt("max-brush-radius", maxBrushRadius); // Get disallowed blocks disallowedBlocks = new HashSet(); diff --git a/src/com/sk89q/worldedit/EditSession.java b/src/com/sk89q/worldedit/EditSession.java index 43869e441..c94ebc97c 100755 --- a/src/com/sk89q/worldedit/EditSession.java +++ b/src/com/sk89q/worldedit/EditSession.java @@ -53,7 +53,7 @@ public class EditSession { /** * World. */ - private LocalWorld world; + protected LocalWorld world; /** * Stores the original blocks before modification. @@ -141,7 +141,7 @@ public class EditSession { * @param blockType * @return Whether the block changed */ - private boolean rawSetBlock(Vector pt, BaseBlock block) { + protected boolean rawSetBlock(Vector pt, BaseBlock block) { int y = pt.getBlockY(); if (y < 0 || y > 127) { diff --git a/src/com/sk89q/worldedit/LocalConfiguration.java b/src/com/sk89q/worldedit/LocalConfiguration.java index beb29d238..a40ec35ac 100644 --- a/src/com/sk89q/worldedit/LocalConfiguration.java +++ b/src/com/sk89q/worldedit/LocalConfiguration.java @@ -43,6 +43,7 @@ public abstract class LocalConfiguration { public SnapshotRepository snapshotRepo = null; public int maxRadius = -1; public int maxSuperPickaxeSize = 5; + public int maxBrushRadius = 6; public boolean logComands = false; public boolean registerHelp = true; public int wandItem = 271; diff --git a/src/com/sk89q/worldedit/LocalSession.java b/src/com/sk89q/worldedit/LocalSession.java index 77843a379..23b0bb6b1 100644 --- a/src/com/sk89q/worldedit/LocalSession.java +++ b/src/com/sk89q/worldedit/LocalSession.java @@ -42,8 +42,9 @@ public class LocalSession { private CuboidClipboard clipboard; private boolean toolControl = true; private boolean superPickaxe = false; - private SuperPickaxeMode superPickaxeMode = new SinglePickaxe(); - private SuperPickaxeMode tool; + private SuperPickaxeMode leftClickMode = new SinglePickaxe(); + private SuperPickaxeMode armSwingMode; + private SuperPickaxeMode rightClickMode; private int maxBlocksChanged = -1; private boolean useInventory; private Snapshot snapshot; @@ -359,29 +360,43 @@ public class LocalSession { /** * @return the superPickaxeMode */ - public SuperPickaxeMode getSuperPickaxeMode() { - return superPickaxeMode; + public SuperPickaxeMode getLeftClickMode() { + return leftClickMode; } /** * @param superPickaxeMode the superPickaxeMode to set */ - public void setSuperPickaxeMode(SuperPickaxeMode superPickaxeMode) { - this.superPickaxeMode = superPickaxeMode; + public void setLeftClickMode(SuperPickaxeMode leftClickMode) { + this.leftClickMode = leftClickMode; } /** * @return the tool */ - public SuperPickaxeMode getTool() { - return tool; + public SuperPickaxeMode getRightClickMode() { + return rightClickMode; } /** * @param tool the tool to set */ - public void setTool(SuperPickaxeMode tool) { - this.tool = tool; + public void setRightClickMode(SuperPickaxeMode rightClickMode) { + this.rightClickMode = rightClickMode; + } + + /** + * @return the arm swing mode + */ + public SuperPickaxeMode getArmSwingMode() { + return armSwingMode; + } + + /** + * @param rightClickMode the tool to set + */ + public void setArmSwingMode(SuperPickaxeMode armSwingMode) { + this.armSwingMode = armSwingMode; } /** diff --git a/src/com/sk89q/worldedit/ReplacingEditSession.java b/src/com/sk89q/worldedit/ReplacingEditSession.java new file mode 100644 index 000000000..11c97ddbc --- /dev/null +++ b/src/com/sk89q/worldedit/ReplacingEditSession.java @@ -0,0 +1,102 @@ +// $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 com.sk89q.worldedit.bags.BlockBag; +import com.sk89q.worldedit.blocks.BaseBlock; + +/** + * An edit session that can be set to not replace existing blocks. + * + * @author sk89q + */ +public class ReplacingEditSession extends EditSession { + /** + * True to prevent replacing. + */ + private boolean noReplace = false; + + /** + * Construct the object. + * + * @param server + * @param world + * @param maxBlocks + */ + public ReplacingEditSession(ServerInterface server, LocalWorld world, + int maxBlocks) { + super(server, world, maxBlocks); + } + + /** + * Construct the object. + * + * @param server + * @param world + * @param maxBlocks + * @param blockBag + */ + public ReplacingEditSession(ServerInterface server, LocalWorld world, + int maxBlocks, BlockBag blockBag) { + super(server, world, maxBlocks, blockBag); + } + + /** + * Enables block replacing. + */ + public void enableReplacing() { + noReplace = false; + } + + /** + * Disables block replacing. + */ + public void disableReplacing() { + noReplace = true; + } + + /** + * Sets a block without changing history. + * + * @param pt + * @param blockType + * @return Whether the block changed + */ + public boolean rawSetBlock(Vector pt, BaseBlock block) { + if (!noReplace) { + return super.rawSetBlock(pt, block); + } + + int y = pt.getBlockY(); + + if (y < 0 || y > 127) { + return false; + } + + int existing = world.getBlockType(pt); + + if (existing != 0) { + return false; + } + + return super.rawSetBlock(pt, block); + } + +} diff --git a/src/com/sk89q/worldedit/WorldEditController.java b/src/com/sk89q/worldedit/WorldEditController.java index 7e47006cf..98efeeb80 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -136,6 +136,7 @@ public class WorldEditController { commands.put("/tree", "Switch to the tree tool"); commands.put("/bigtree", "Switch to the big tree tool"); commands.put("/repl", "[ID] - Switch to the block replacer tool"); + commands.put("/brush", "[ID] - Switch to the sphere brush tool"); commands.put("//expand", "[Num] - Expands the selection"); commands.put("//contract", "[Num] - Contracts the selection"); commands.put("//shift", "[Num] - Shift the selection"); @@ -648,7 +649,7 @@ public class WorldEditController { } checkArgs(split, 0, 0, split[0]); - session.setSuperPickaxeMode(new SinglePickaxe()); + session.setLeftClickMode(new SinglePickaxe()); session.enableSuperPickAxe(); player.print("Mode changed. Left click with a pickaxe. // to disable."); return true; @@ -672,7 +673,7 @@ public class WorldEditController { return true; } - session.setSuperPickaxeMode( + session.setLeftClickMode( recur ? new RecursivePickaxe(range) : new AreaPickaxe(range)); session.enableSuperPickAxe(); player.print("Mode changed. Left click with a pickaxe. // to disable."); @@ -681,21 +682,21 @@ public class WorldEditController { // Tree tool } else if (split[0].equalsIgnoreCase("/tree")) { checkArgs(split, 0, 0, split[0]); - session.setTool(new TreePlanter()); + session.setRightClickMode(new TreePlanter()); player.print("Tree tool equipped. Right click with a pickaxe."); return true; // Big tree tool } else if (split[0].equalsIgnoreCase("/bigtree")) { checkArgs(split, 0, 0, split[0]); - session.setTool(new BigTreePlanter()); + session.setRightClickMode(new BigTreePlanter()); player.print("Big 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()); + session.setRightClickMode(new QueryTool()); player.print("Info tool equipped. Right click with a pickaxe."); return true; @@ -703,14 +704,36 @@ public class WorldEditController { } else if (split[0].equalsIgnoreCase("/repl")) { checkArgs(split, 1, 1, split[0]); BaseBlock targetBlock = getBlock(player, split[1]); - session.setTool(new BlockReplacer(targetBlock)); + session.setRightClickMode(new BlockReplacer(targetBlock)); player.print("Block replacer tool equipped. Right click with a pickaxe."); return true; + // Sphere brush tool + } else if (split[0].equalsIgnoreCase("/brush")) { + checkArgs(split, 1, 3, split[0]); + int radius = split.length > 2 ? Integer.parseInt(split[2]) : 2; + boolean nonReplacing = split.length > 3 + ? (split[3].equalsIgnoreCase("true") + || split[3].equalsIgnoreCase("yes")) : false; + if (radius > config.maxBrushRadius) { + player.printError("Maximum allowed brush radius: " + + config.maxBrushRadius); + return true; + } + BaseBlock targetBlock = getBlock(player, split[1]); + session.setArmSwingMode(new SphereBrush(targetBlock, radius, nonReplacing)); + if (nonReplacing) { + player.print("Non-replacing sphere brush tool equipped."); + } else { + player.print("Sphere brush tool equipped. Right click with a pickaxe."); + } + return true; + // No tool } else if (split[0].equalsIgnoreCase("/none")) { checkArgs(split, 0, 0, split[0]); - session.setTool(null); + session.setArmSwingMode(null); + session.setRightClickMode(null); player.print("Now no longer equipping a tool."); return true; @@ -1778,8 +1801,14 @@ public class WorldEditController { * @param player */ public void handleArmSwing(LocalPlayer player) { - if (!canUseCommand(player, "/")) - return; + LocalSession session = getSession(player); + + if (player.isHoldingPickAxe()) { + if (session.getArmSwingMode() != null) { + session.getArmSwingMode().act(server, config, + player, session, null); + } + } } /** @@ -1792,10 +1821,6 @@ public class WorldEditController { public boolean handleBlockRightClick(LocalPlayer player, WorldVector clicked) { int itemInHand = player.getItemInHand(); - // This prevents needless sessions from being created - if (!hasSession(player) && !(itemInHand == config.wandItem && - canUseCommand(player, "/pos2"))) { return false; } - LocalSession session = getSession(player); if (itemInHand == config.wandItem && session.isToolControlEnabled() @@ -1809,8 +1834,8 @@ public class WorldEditController { } return true; - } else if (player.isHoldingPickAxe() && session.getTool() != null) { - return session.getTool().act(server, config, player, session, clicked); + } else if (player.isHoldingPickAxe() && session.getRightClickMode() != null) { + return session.getRightClickMode().act(server, config, player, session, clicked); } return false; @@ -1856,8 +1881,8 @@ public class WorldEditController { return true; } } else if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) { - if (session.getSuperPickaxeMode() != null) { - return session.getSuperPickaxeMode().act(server, config, + if (session.getLeftClickMode() != null) { + return session.getLeftClickMode().act(server, config, player, session, clicked); } } diff --git a/src/com/sk89q/worldedit/superpickaxe/SphereBrush.java b/src/com/sk89q/worldedit/superpickaxe/SphereBrush.java new file mode 100644 index 000000000..06343aad6 --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/SphereBrush.java @@ -0,0 +1,70 @@ +// $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; + +/** + * Builds a sphere at the place being looked at. + * + * @author sk89q + */ +public class SphereBrush implements SuperPickaxeMode { + private BaseBlock targetBlock; + private int radius; + private boolean nonReplacing; + + public SphereBrush(BaseBlock targetBlock, int radius, boolean nonReplacing) { + this.targetBlock = targetBlock; + this.radius = radius; + this.nonReplacing = nonReplacing; + } + + @Override + public boolean act(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, WorldVector clicked) { + WorldVector target = player.getBlockTrace(500); + + if (target == null) { + player.printError("No block in sight!"); + return true; + } + + ReplacingEditSession editSession = new ReplacingEditSession(server, target.getWorld(), + session.getBlockChangeLimit()); + + if (nonReplacing) { + editSession.disableReplacing(); + } + + try { + editSession.makeSphere(target, targetBlock, radius, true); + } catch (MaxChangedBlocksException e) { + player.printError("Max blocks change limit reached."); + } finally { + editSession.enableReplacing(); + session.remember(editSession); + } + + return true; + } + +}