diff --git a/plugin.yml b/plugin.yml index d53ef2cac..09f53a54a 100644 --- a/plugin.yml +++ b/plugin.yml @@ -294,6 +294,9 @@ commands: none: description: Turn off all superpickaxe alternate modes usage: / + farwand: + description: Wand tool at a distance + usage: / tree: description: Tree generator tool usage: / [type] diff --git a/src/main/java/com/sk89q/worldedit/WorldEdit.java b/src/main/java/com/sk89q/worldedit/WorldEdit.java index 16e8bd1ee..a9e936929 100644 --- a/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -879,26 +879,31 @@ public class WorldEdit { } /** - * Called on left click (not on a block). + * Called on arm swing. * * @param player * @return */ - public boolean handleLeftClick(LocalPlayer player) { + public boolean handleArmSwing(LocalPlayer player) { LocalSession session = getSession(player); - WorldVector pos = player.getSolidBlockTrace(config.navigationWandMaxDistance); - if (player.getItemInHand() == config.wandItem) { - return selectFirstPoint(player, session, pos); - } else if (player.getItemInHand() == config.navigationWand + if (player.getItemInHand() == config.navigationWand && config.navigationWandMaxDistance > 0 && player.hasPermission("worldedit.navigation.jumpto")) { + WorldVector pos = player.getSolidBlockTrace(config.navigationWandMaxDistance); if (pos != null) { player.findFreePosition(pos); } else { player.printError("No block in sight (or too far)!"); } } - + + Tool tool = session.getTool(player.getItemInHand()); + if (tool != null && tool instanceof DoubleActionTraceTool) { + if (tool.canUse(player)) { + ((DoubleActionTraceTool) tool).actSecondary(server, config, player, session); + return true; + } + } return false; } @@ -918,16 +923,13 @@ public class WorldEdit { if (!player.passThroughForwardWall(40)) { player.printError("Nothing to pass through!"); } - } else if (player.getItemInHand() == config.wandItem) { - WorldVector pos = player.getSolidBlockTrace(config.navigationWandMaxDistance); - return selectSecondPoint(player, session, pos); } Tool tool = session.getTool(player.getItemInHand()); if (tool != null && tool instanceof TraceTool) { if (tool.canUse(player)) { - ((TraceTool)tool).act(server, config, player, session); + ((TraceTool) tool).actPrimary(server, config, player, session); return true; } } @@ -943,10 +945,18 @@ public class WorldEdit { * @return false if you want the action to go through */ public boolean handleBlockRightClick(LocalPlayer player, WorldVector clicked) { + int itemInHand = player.getItemInHand(); + LocalSession session = getSession(player); - if (player.getItemInHand() == config.wandItem) { - return selectSecondPoint(player, session, clicked); + if (itemInHand == config.wandItem && session.isToolControlEnabled() + && player.hasPermission("worldedit.selection.pos")) { + RegionSelector selector = session.getRegionSelector(player.getWorld()); + if (selector.selectSecondary(clicked)) { + selector.explainSecondarySelection(player, session, clicked); + } + + return true; } Tool tool = session.getTool(player.getItemInHand()); @@ -971,8 +981,22 @@ public class WorldEdit { public boolean handleBlockLeftClick(LocalPlayer player, WorldVector clicked) { LocalSession session = getSession(player); - if (player.getItemInHand() == config.wandItem) { - return selectFirstPoint(player, session, clicked); + if (player.getItemInHand() == config.wandItem) { + if (session.isToolControlEnabled() + && player.hasPermission("worldedit.selection.pos")) { + // Bug workaround + if (clicked.getBlockX() == 0 && clicked.getBlockY() == 0 + && clicked.getBlockZ() == 0) { + return false; + } + + RegionSelector selector = session.getRegionSelector(player.getWorld()); + if (selector.selectPrimary(clicked)) { + selector.explainPrimarySelection(player, session, clicked); + } + + return true; + } } else if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) { if (session.getSuperPickaxe() != null) { if (session.getSuperPickaxe().canUse(player)) { @@ -991,40 +1015,6 @@ public class WorldEdit { } } - return false; - } - - private boolean selectFirstPoint(LocalPlayer player, LocalSession session, WorldVector clicked) - { - if (session.isToolControlEnabled() - && player.hasPermission("worldedit.selection.pos")) { - // Bug workaround - if (clicked.getBlockX() == 0 && clicked.getBlockY() == 0 - && clicked.getBlockZ() == 0) { - return false; - } - - RegionSelector selector = session.getRegionSelector(player.getWorld()); - if (selector.selectPrimary(clicked)) { - selector.explainPrimarySelection(player, session, clicked); - } - - return true; - } - return false; - } - - private boolean selectSecondPoint(LocalPlayer player, LocalSession session, WorldVector clicked) - { - if (session.isToolControlEnabled() - && player.hasPermission("worldedit.selection.pos")) { - RegionSelector selector = session.getRegionSelector(player.getWorld()); - if (selector.selectSecondary(clicked)) { - selector.explainSecondarySelection(player, session, clicked); - } - - return true; - } return false; } diff --git a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java index 6c5c9ab37..a7d108086 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlayerListener.java @@ -94,8 +94,14 @@ public class WorldEditPlayerListener extends PlayerListener { LocalPlayer player = wrapPlayer(event.getPlayer()); if (plugin.getWorldEdit().handleBlockLeftClick(player, pos)) { + event.setCancelled(true); + } + + if (plugin.getWorldEdit().handleArmSwing(wrapPlayer(event.getPlayer()))) { event.setCancelled(true); - } else if (plugin.getWorldEdit().handleLeftClick(wrapPlayer(event.getPlayer()))) { + } + } else if (event.getAction() == Action.LEFT_CLICK_AIR) { + if (plugin.getWorldEdit().handleArmSwing(wrapPlayer(event.getPlayer()))) { event.setCancelled(true); } } else if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { @@ -106,17 +112,15 @@ public class WorldEditPlayerListener extends PlayerListener { if (plugin.getWorldEdit().handleBlockRightClick(player, pos)) { event.setCancelled(true); - } else if (plugin.getWorldEdit().handleRightClick(wrapPlayer(event.getPlayer()))) { + } + + if (plugin.getWorldEdit().handleRightClick(wrapPlayer(event.getPlayer()))) { event.setCancelled(true); } } else if (event.getAction() == Action.RIGHT_CLICK_AIR) { if (plugin.getWorldEdit().handleRightClick(wrapPlayer(event.getPlayer()))) { event.setCancelled(true); } - } else if (event.getAction() == Action.LEFT_CLICK_AIR) { - if (plugin.getWorldEdit().handleLeftClick(wrapPlayer(event.getPlayer()))) { - event.setCancelled(true); - } } } diff --git a/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java b/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java index cf2be9510..e6e80cc25 100644 --- a/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java @@ -176,4 +176,20 @@ public class ToolCommands { player.print("Floating tree remover tool bound to " + ItemType.toHeldName(player.getItemInHand()) + "."); } + + @Command( + aliases = {"farwand"}, + usage = "", + desc = "Wand at a distance tool", + min = 0, + max = 0 + ) + @CommandPermissions({"worldedit.tool.farwand"}) + public static void farwand(CommandContext args, WorldEdit we, + LocalSession session, LocalPlayer player, EditSession editSession) + throws WorldEditException { + + session.setTool(player.getItemInHand(), new DistanceWand()); + player.print("Far wand tool bound to " + ItemType.toHeldName(player.getItemInHand()) + "."); + } } diff --git a/src/main/java/com/sk89q/worldedit/tools/BrushTool.java b/src/main/java/com/sk89q/worldedit/tools/BrushTool.java index ddd50dd19..b34dfc3d6 100644 --- a/src/main/java/com/sk89q/worldedit/tools/BrushTool.java +++ b/src/main/java/com/sk89q/worldedit/tools/BrushTool.java @@ -36,8 +36,8 @@ import com.sk89q.worldedit.tools.brushes.SphereBrush; * @author sk89q */ public class BrushTool implements TraceTool { - private static int MAX_RANGE = 500; - private int range = -1; + protected static int MAX_RANGE = 500; + protected int range = -1; private Mask mask = null; private Brush brush = new SphereBrush(); private Pattern material = new SingleBlockPattern(new BaseBlock(BlockID.COBBLESTONE)); @@ -164,7 +164,7 @@ public class BrushTool implements TraceTool { * @param session * @return true to deny */ - public boolean act(ServerInterface server, LocalConfiguration config, + public boolean actPrimary(ServerInterface server, LocalConfiguration config, LocalPlayer player, LocalSession session) { WorldVector target = null; if (this.range > -1) { diff --git a/src/main/java/com/sk89q/worldedit/tools/DistanceWand.java b/src/main/java/com/sk89q/worldedit/tools/DistanceWand.java new file mode 100644 index 000000000..844c179e0 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/tools/DistanceWand.java @@ -0,0 +1,96 @@ +// $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.tools; + +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.bags.BlockBag; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockType; +import com.sk89q.worldedit.regions.RegionSelector; + +/** + * A wand that can be used at a distance. + * + * @author wizjany + */ +public class DistanceWand extends BrushTool implements DoubleActionTraceTool { + + public DistanceWand() { + super("worldedit.wand"); + } + + public boolean canUse(LocalPlayer player) { + return player.hasPermission("worldedit.wand"); + } + + public boolean actSecondary(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session) { + if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) { + WorldVector target = getTarget(player); + if (target == null) return true; + + RegionSelector selector = session.getRegionSelector(player.getWorld()); + if (selector.selectPrimary(target)) { + selector.explainPrimarySelection(player, session, target); + } + return true; + + } + return false; + + } + + @Override + public boolean actPrimary(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session) { + if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) { + WorldVector target = getTarget(player); + if (target == null) return true; + + RegionSelector selector = session.getRegionSelector(player.getWorld()); + if (selector.selectSecondary(target)) { + selector.explainSecondarySelection(player, session, target); + } + return true; + + } + return false; + } + + public WorldVector getTarget(LocalPlayer player) { + WorldVector target = null; + if (this.range > -1) { + target = player.getBlockTrace(getRange(), true); + } else { + target = player.getBlockTrace(MAX_RANGE); + } + + if (target == null) { + player.printError("No block in sight!"); + return null; + } + + // Bug workaround + if (target.getBlockX() == 0 && target.getBlockY() == 0 && target.getBlockZ() == 0) { + return null; + } + return target; + } +} diff --git a/src/main/java/com/sk89q/worldedit/tools/DoubleActionTraceTool.java b/src/main/java/com/sk89q/worldedit/tools/DoubleActionTraceTool.java new file mode 100644 index 000000000..c3ea0272b --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/tools/DoubleActionTraceTool.java @@ -0,0 +1,44 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010, 2011 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.tools; + +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LocalPlayer; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.ServerInterface; +import com.sk89q.worldedit.WorldVector; + +/** + * Represents a trace tool that also has a secondary/primary function. + */ +public interface DoubleActionTraceTool extends TraceTool { + /** + * Perform the secondary action. Should return true to deny the default + * action. + * + * @param server + * @param config + * @param player + * @param session + * @return true to deny + */ + public boolean actSecondary(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session); +} diff --git a/src/main/java/com/sk89q/worldedit/tools/TraceTool.java b/src/main/java/com/sk89q/worldedit/tools/TraceTool.java index 661e0dafb..be1a6dfa0 100644 --- a/src/main/java/com/sk89q/worldedit/tools/TraceTool.java +++ b/src/main/java/com/sk89q/worldedit/tools/TraceTool.java @@ -40,6 +40,6 @@ public interface TraceTool extends Tool { * @param session * @return true to deny */ - public boolean act(ServerInterface server, LocalConfiguration config, + public boolean actPrimary(ServerInterface server, LocalConfiguration config, LocalPlayer player, LocalSession session); }