diff --git a/src/com/sk89q/worldedit/ReplacingExistingEditSession.java b/src/com/sk89q/worldedit/ReplacingExistingEditSession.java new file mode 100644 index 000000000..0dba5becf --- /dev/null +++ b/src/com/sk89q/worldedit/ReplacingExistingEditSession.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 only replace existing blocks. + * + * @author sk89q + */ +public class ReplacingExistingEditSession extends EditSession { + /** + * True to replace existing. + */ + private boolean replaceExisting = false; + + /** + * Construct the object. + * + * @param server + * @param world + * @param maxBlocks + */ + public ReplacingExistingEditSession(ServerInterface server, LocalWorld world, + int maxBlocks) { + super(server, world, maxBlocks); + } + + /** + * Construct the object. + * + * @param server + * @param world + * @param maxBlocks + * @param blockBag + */ + public ReplacingExistingEditSession(ServerInterface server, LocalWorld world, + int maxBlocks, BlockBag blockBag) { + super(server, world, maxBlocks, blockBag); + } + + /** + * Enables block replacing. + */ + public void enableReplacing() { + replaceExisting = true; + } + + /** + * Disables block replacing. + */ + public void disableReplacing() { + replaceExisting = false; + } + + /** + * Sets a block without changing history. + * + * @param pt + * @param blockType + * @return Whether the block changed + */ + public boolean rawSetBlock(Vector pt, BaseBlock block) { + if (!replaceExisting) { + 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 53a874d3b..6c8d992de 100644 --- a/src/com/sk89q/worldedit/WorldEditController.java +++ b/src/com/sk89q/worldedit/WorldEditController.java @@ -172,6 +172,7 @@ public class WorldEditController { 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("/rbrush", "[ID] - Switch to the replacing sphere brush tool"); } /** @@ -735,10 +736,24 @@ public class WorldEditController { if (nonReplacing) { player.print("Non-replacing sphere brush tool equipped."); } else { - player.print("Sphere brush tool equipped. Right click with a pickaxe."); + player.print("Sphere brush tool equipped. Swing with a pickaxe."); } return true; + // Sphere brush tool + } else if (split[0].equalsIgnoreCase("/rbrush")) { + checkArgs(split, 1, 3, split[0]); + int radius = split.length > 2 ? Integer.parseInt(split[2]) : 2; + if (radius > config.maxBrushRadius) { + player.printError("Maximum allowed brush radius: " + + config.maxBrushRadius); + return true; + } + BaseBlock targetBlock = getBlock(player, split[1]); + session.setArmSwingMode(new ReplacingSphereBrush(targetBlock, radius)); + player.print("Replacing sphere brush tool equipped. Swing with a pickaxe."); + return true; + // No tool } else if (split[0].equalsIgnoreCase("/none")) { checkArgs(split, 0, 0, split[0]); @@ -1880,16 +1895,20 @@ public class WorldEditController { * Called on arm swing. * * @param player + * @return */ - public void handleArmSwing(LocalPlayer player) { + public boolean handleArmSwing(LocalPlayer player) { LocalSession session = getSession(player); if (player.isHoldingPickAxe()) { if (session.getArmSwingMode() != null) { session.getArmSwingMode().act(server, config, player, session, null); + return true; } } + + return false; } /** diff --git a/src/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java b/src/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java index aa07df118..8b064f895 100644 --- a/src/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java +++ b/src/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.bukkit; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerItemEvent; import org.bukkit.event.player.PlayerListener; /** @@ -81,6 +82,17 @@ public class WorldEditPlayerListener extends PlayerListener { } } + /** + * Called when a player uses an item + * + * @param event Relevant event details + */ + public void onPlayerItem(PlayerItemEvent event) { + if (plugin.controller.handleArmSwing(wrapPlayer(event.getPlayer()))) { + event.setCancelled(true); + } + } + private BukkitPlayer wrapPlayer(Player player) { return new BukkitPlayer(plugin, plugin.server, player); } diff --git a/src/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/src/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index e8c8361a5..cefbac2b1 100644 --- a/src/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/src/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -91,12 +91,12 @@ public class WorldEditPlugin extends JavaPlugin { playerListener, Priority.Normal, this); getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, playerListener, Priority.Normal, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_ITEM, + playerListener, Priority.Normal, this); getServer().getPluginManager().registerEvent(Event.Type.BLOCK_DAMAGED, blockListener, Priority.Normal, this); getServer().getPluginManager().registerEvent(Event.Type.BLOCK_RIGHTCLICKED, blockListener, Priority.Normal, this); - getServer().getPluginManager().registerEvent(Event.Type.BLOCK_RIGHTCLICKED, - blockListener, Priority.Normal, this); permsListener.register(this); } diff --git a/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java b/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java index 52007e17c..9016e704e 100644 --- a/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java +++ b/src/com/sk89q/worldedit/superpickaxe/BlockReplacer.java @@ -48,7 +48,9 @@ public class BlockReplacer implements SuperPickaxeMode { editSession.setBlock(clicked, targetBlock); } catch (MaxChangedBlocksException e) { } finally { - bag.flushChanges(); + if (bag != null) { + bag.flushChanges(); + } session.remember(editSession); } diff --git a/src/com/sk89q/worldedit/superpickaxe/ReplacingSphereBrush.java b/src/com/sk89q/worldedit/superpickaxe/ReplacingSphereBrush.java new file mode 100644 index 000000000..364225dac --- /dev/null +++ b/src/com/sk89q/worldedit/superpickaxe/ReplacingSphereBrush.java @@ -0,0 +1,73 @@ +// $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.bags.BlockBag; +import com.sk89q.worldedit.blocks.BaseBlock; + +/** + * Builds a sphere at the place being looked at. + * + * @author sk89q + */ +public class ReplacingSphereBrush implements SuperPickaxeMode { + private BaseBlock targetBlock; + private int radius; + + public ReplacingSphereBrush(BaseBlock targetBlock, int radius) { + this.targetBlock = targetBlock; + this.radius = radius; + } + + @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; + } + + BlockBag bag = session.getBlockBag(player); + + ReplacingExistingEditSession editSession = + new ReplacingExistingEditSession(server, target.getWorld(), + session.getBlockChangeLimit(), bag); + + editSession.enableReplacing(); + + try { + editSession.makeSphere(target, targetBlock, radius, true); + } catch (MaxChangedBlocksException e) { + player.printError("Max blocks change limit reached."); + } finally { + if (bag != null) { + bag.flushChanges(); + } + editSession.enableReplacing(); + session.remember(editSession); + } + + return true; + } + +} diff --git a/src/com/sk89q/worldedit/superpickaxe/SphereBrush.java b/src/com/sk89q/worldedit/superpickaxe/SphereBrush.java index 7badd5548..fe83e80ad 100644 --- a/src/com/sk89q/worldedit/superpickaxe/SphereBrush.java +++ b/src/com/sk89q/worldedit/superpickaxe/SphereBrush.java @@ -63,7 +63,9 @@ public class SphereBrush implements SuperPickaxeMode { } catch (MaxChangedBlocksException e) { player.printError("Max blocks change limit reached."); } finally { - bag.flushChanges(); + if (bag != null) { + bag.flushChanges(); + } editSession.enableReplacing(); session.remember(editSession); }