From c0f2557f15268fcd2fa6ab46050990d11a76f2eb Mon Sep 17 00:00:00 2001 From: wizjany Date: Fri, 28 Jun 2019 15:45:16 -0400 Subject: [PATCH] Make the selection wand and navigation wand normal tools. (#493) This means users can bind and unbind them to any item, like other tools. By default, the items in config will be automatically bound. After setting a different item via `//selwand` or `//navwand`, that item will subsequently be used for that user. Also add -n to //wand to get a navwand. Also various other tool-related cleanup. --- .../com/sk89q/worldedit/LocalSession.java | 51 ++++-- .../worldedit/command/SelectionCommands.java | 48 ++++-- .../sk89q/worldedit/command/ToolCommands.java | 31 ++++ .../worldedit/command/tool/AreaPickaxe.java | 12 +- .../command/tool/BlockDataCyler.java | 10 +- .../worldedit/command/tool/BlockReplacer.java | 5 +- .../worldedit/command/tool/BlockTool.java | 10 ++ .../worldedit/command/tool/DistanceWand.java | 44 ++--- .../command/tool/DoubleActionBlockTool.java | 10 ++ .../command/tool/DoubleActionTraceTool.java | 9 ++ .../command/tool/FloatingTreeRemover.java | 2 +- .../command/tool/LongRangeBuildTool.java | 4 +- .../command/tool/NavigationWand.java | 68 ++++++++ .../worldedit/command/tool/QueryTool.java | 3 +- .../command/tool/RecursivePickaxe.java | 11 +- .../worldedit/command/tool/SelectionWand.java | 59 +++++++ .../worldedit/command/tool/SinglePickaxe.java | 8 +- .../worldedit/command/tool/TraceTool.java | 9 ++ .../worldedit/command/tool/TreePlanter.java | 4 +- .../extension/platform/PlatformManager.java | 151 +++++------------- .../worldedit/session/SessionManager.java | 36 ++++- 21 files changed, 394 insertions(+), 191 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index c71e7d1aa..46a73b131 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -28,6 +28,8 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.command.tool.BlockTool; import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.InvalidToolBindException; +import com.sk89q.worldedit.command.tool.NavigationWand; +import com.sk89q.worldedit.command.tool.SelectionWand; import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; @@ -48,7 +50,6 @@ import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.snapshot.Snapshot; import javax.annotation.Nullable; @@ -67,11 +68,11 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class LocalSession { - public transient static int MAX_HISTORY_SIZE = 15; + public static transient int MAX_HISTORY_SIZE = 15; // Non-session related fields private transient LocalConfiguration config; - private transient final AtomicBoolean dirty = new AtomicBoolean(); + private final transient AtomicBoolean dirty = new AtomicBoolean(); private transient int failedCuiAttempts = 0; // Session related @@ -80,7 +81,6 @@ public class LocalSession { private transient LinkedList history = new LinkedList<>(); private transient int historyPointer = 0; private transient ClipboardHolder clipboard; - private transient boolean toolControl = true; private transient boolean superPickaxe = false; private transient BlockTool pickaxeMode = new SinglePickaxe(); private transient Map tools = new HashMap<>(); @@ -100,6 +100,8 @@ public class LocalSession { private String lastScript; private RegionSelectorType defaultSelector; private boolean useServerCUI = false; // Save this to not annoy players. + private String wandItem; + private String navWandItem; /** * Construct the object. @@ -387,21 +389,20 @@ public class LocalSession { } /** - * See if tool control is enabled. - * - * @return true if enabled + * @return true always - see deprecation notice + * @deprecated The wand is now a tool that can be bound/unbound. */ + @Deprecated public boolean isToolControlEnabled() { - return toolControl; + return true; } /** - * Change tool control setting. - * - * @param toolControl true to enable tool control + * @param toolControl unused - see deprecation notice + * @deprecated The wand is now a tool that can be bound/unbound. */ + @Deprecated public void setToolControl(boolean toolControl) { - this.toolControl = toolControl; } /** @@ -594,10 +595,13 @@ public class LocalSession { public void setTool(ItemType item, @Nullable Tool tool) throws InvalidToolBindException { if (item.hasBlockType()) { throw new InvalidToolBindException(item, "Blocks can't be used"); - } else if (item == ItemTypes.get(config.wandItem)) { - throw new InvalidToolBindException(item, "Already used for the wand"); - } else if (item == ItemTypes.get(config.navigationWand)) { - throw new InvalidToolBindException(item, "Already used for the navigation wand"); + } + if (tool instanceof SelectionWand) { + this.wandItem = item.getId(); + setDirty(); + } else if (tool instanceof NavigationWand) { + this.navWandItem = item.getId(); + setDirty(); } this.tools.put(item, tool); @@ -954,4 +958,19 @@ public class LocalSession { this.mask = mask; } + /** + * Get the preferred wand item for this user, or {@code null} to use the default + * @return item id of wand item, or {@code null} + */ + public String getWandItem() { + return wandItem; + } + + /** + * Get the preferred navigation wand item for this user, or {@code null} to use the default + * @return item id of nav wand item, or {@code null} + */ + public String getNavWandItem() { + return navWandItem; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 155385c52..31aba51e9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -25,6 +25,8 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.command.argument.SelectorChoice; +import com.sk89q.worldedit.command.tool.NavigationWand; +import com.sk89q.worldedit.command.tool.SelectionWand; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; @@ -56,9 +58,13 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.component.CommandListBox; import com.sk89q.worldedit.util.formatting.component.SubtleFormat; import com.sk89q.worldedit.util.formatting.component.TextComponentProducer; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.storage.ChunkStore; import org.enginehub.piston.annotation.Command; @@ -246,24 +252,42 @@ public class SelectionCommands { desc = "Get the wand object" ) @CommandPermissions("worldedit.wand") - public void wand(Player player) throws WorldEditException { - player.giveItem(new BaseItemStack(ItemTypes.get(we.getConfiguration().wandItem), 1)); - player.print("Left click: select pos #1; Right click: select pos #2"); + public void wand(Player player, LocalSession session, + @Switch(name = 'n', desc = "Get a navigation wand") boolean navWand) throws WorldEditException { + String wandId = navWand ? session.getNavWandItem() : session.getWandItem(); + if (wandId == null) { + wandId = navWand ? we.getConfiguration().navigationWand : we.getConfiguration().wandItem; + } + ItemType itemType = ItemTypes.get(wandId); + if (itemType == null) { + player.printError("Wand item is mis-configured or disabled."); + return; + } + player.giveItem(new BaseItemStack(itemType, 1)); + if (navWand) { + session.setTool(itemType, new NavigationWand()); + player.print("Left click: jump to location; Right click: pass through walls"); + } else { + session.setTool(itemType, new SelectionWand()); + player.print("Left click: select pos #1; Right click: select pos #2"); + } } @Command( name = "toggleeditwand", - desc = "Toggle functionality of the edit wand" + desc = "Remind the user that the wand is now a tool and can be unbound with /none." ) @CommandPermissions("worldedit.wand.toggle") - public void toggleWand(Player player, LocalSession session) throws WorldEditException { - session.setToolControl(!session.isToolControlEnabled()); - - if (session.isToolControlEnabled()) { - player.print("Edit wand enabled."); - } else { - player.print("Edit wand disabled."); - } + public void toggleWand(Player player) { + player.print(TextComponent.of("The selection wand is now a normal tool. You can disable it with ") + .append(TextComponent.of("/none", TextColor.AQUA).clickEvent( + ClickEvent.of(ClickEvent.Action.RUN_COMMAND, "/none"))) + .append(TextComponent.of(" and rebind it to any item with ")) + .append(TextComponent.of("//selwand", TextColor.AQUA).clickEvent( + ClickEvent.of(ClickEvent.Action.RUN_COMMAND, "//selwand"))) + .append(TextComponent.of(" or get a new wand with ")) + .append(TextComponent.of("//wand", TextColor.AQUA).clickEvent( + ClickEvent.of(ClickEvent.Action.RUN_COMMAND, "//wand")))); } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 8242cfec9..c3a57a1ad 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -30,7 +30,9 @@ import com.sk89q.worldedit.command.tool.DistanceWand; import com.sk89q.worldedit.command.tool.FloatingTreeRemover; import com.sk89q.worldedit.command.tool.FloodFillTool; import com.sk89q.worldedit.command.tool.LongRangeBuildTool; +import com.sk89q.worldedit.command.tool.NavigationWand; import com.sk89q.worldedit.command.tool.QueryTool; +import com.sk89q.worldedit.command.tool.SelectionWand; import com.sk89q.worldedit.command.tool.TreePlanter; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; @@ -39,6 +41,7 @@ import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.world.item.ItemType; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; @@ -61,6 +64,32 @@ public class ToolCommands { player.print("Tool unbound from your current item."); } + @Command( + name = "/selwand", + aliases = "selwand", + desc = "Selection wand tool" + ) + @CommandPermissions("worldedit.selection.pos") + public void selwand(Player player, LocalSession session) throws WorldEditException { + + final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); + session.setTool(itemType, new SelectionWand()); + player.print("Selection wand bound to " + itemType.getName() + "."); + } + + @Command( + name = "/navwand", + aliases = "navwand", + desc = "Navigation wand tool" + ) + @CommandPermissions({"worldedit.command.jumpto.tool", "worldedit.command.thru.tool"}) + public void navwand(Player player, LocalSession session) throws WorldEditException { + + BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); + session.setTool(itemStack.getType(), new NavigationWand()); + player.print("Navigation wand bound to " + itemStack.getType().getName() + "."); + } + @Command( name = "info", desc = "Block information tool" @@ -82,6 +111,7 @@ public class ToolCommands { public void tree(Player player, LocalSession session, @Arg(desc = "Type of tree to generate", def = "tree") TreeGenerator.TreeType type) throws WorldEditException { + BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); session.setTool(itemStack.getType(), new TreePlanter(type)); player.print("Tree tool bound to " + itemStack.getType().getName() + "."); @@ -95,6 +125,7 @@ public class ToolCommands { public void repl(Player player, LocalSession session, @Arg(desc = "The pattern of blocks to place") Pattern pattern) throws WorldEditException { + BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); session.setTool(itemStack.getType(), new BlockReplacer(pattern)); player.print("Block replacer tool bound to " + itemStack.getType().getName() + "."); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java index 35b3a0c3e..662f8d71e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -48,18 +49,18 @@ public class AreaPickaxe implements BlockTool { } @Override - public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { int ox = clicked.getBlockX(); int oy = clicked.getBlockY(); int oz = clicked.getBlockZ(); BlockType initialType = clicked.getExtent().getBlock(clicked.toVector().toBlockPoint()).getBlockType(); if (initialType.getMaterial().isAir()) { - return true; + return false; } if (initialType == BlockTypes.BEDROCK && !player.canDestroyBedrock()) { - return true; + return false; } try (EditSession editSession = session.createEditSession(player)) { @@ -74,9 +75,10 @@ public class AreaPickaxe implements BlockTool { continue; } - ((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType, clicked.toVector().toBlockPoint().distanceSq(pos)); - editSession.setBlock(pos, BlockTypes.AIR.getDefaultState()); + + ((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType, + clicked.toVector().toBlockPoint().distanceSq(pos)); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java index 5440a687f..ac3376d8d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java @@ -50,8 +50,8 @@ public class BlockDataCyler implements DoubleActionBlockTool { private Map> selectedProperties = new HashMap<>(); - private boolean handleCycle(Platform server, LocalConfiguration config, - Player player, LocalSession session, Location clicked, boolean forward) { + private boolean handleCycle(LocalConfiguration config, Player player, LocalSession session, + Location clicked, boolean forward) { World world = (World) clicked.getExtent(); @@ -88,7 +88,7 @@ public class BlockDataCyler implements DoubleActionBlockTool { try { editSession.setBlock(blockPoint, newBlock); - player.print("Value of " + currentProperty.getName() + " is now " + currentProperty.getValues().get(index).toString()); + player.print("Value of " + currentProperty.getName() + " is now " + currentProperty.getValues().get(index)); } catch (MaxChangedBlocksException e) { player.printError("Max blocks change limit reached."); } finally { @@ -110,12 +110,12 @@ public class BlockDataCyler implements DoubleActionBlockTool { @Override public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { - return handleCycle(server, config, player, session, clicked, true); + return handleCycle(config, player, session, clicked, true); } @Override public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { - return handleCycle(server, config, player, session, clicked, false); + return handleCycle(config, player, session, clicked, false); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java index 9fcdf6754..8cc85d705 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java @@ -30,6 +30,7 @@ import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.block.BlockState; /** @@ -49,7 +50,7 @@ public class BlockReplacer implements DoubleActionBlockTool { } @Override - public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { BlockBag bag = session.getBlockBag(player); try (EditSession editSession = session.createEditSession(player)) { @@ -72,7 +73,7 @@ public class BlockReplacer implements DoubleActionBlockTool { @Override - public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { + public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { BlockState targetBlock = player.getWorld().getBlock(clicked.toVector().toBlockPoint()); if (targetBlock != null) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java index 139fbd640..0ee513d75 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockTool.java @@ -27,5 +27,15 @@ import com.sk89q.worldedit.util.Location; public interface BlockTool extends Tool { + /** + * Perform the primary action of this tool. + * + * @param server + * @param config + * @param player + * @param session + * @param clicked + * @return true to cancel the original event which triggered this action (if possible) + */ boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java index 48d3dbf7a..781d24f8c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java @@ -22,7 +22,6 @@ package com.sk89q.worldedit.command.tool; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; import com.sk89q.worldedit.function.mask.Mask; @@ -36,46 +35,33 @@ import com.sk89q.worldedit.util.Location; public class DistanceWand extends BrushTool implements DoubleActionTraceTool { public DistanceWand() { - super("worldedit.wand"); - } - - @Override - public boolean canUse(Actor player) { - return player.hasPermission("worldedit.wand"); + super("worldedit.selection.pos"); } @Override public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) { - if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) { - Location target = getTarget(player); - if (target == null) return true; - - RegionSelector selector = session.getRegionSelector(player.getWorld()); - BlockVector3 blockPoint = target.toVector().toBlockPoint(); - if (selector.selectPrimary(blockPoint, ActorSelectorLimits.forActor(player))) { - selector.explainPrimarySelection(player, session, blockPoint); - } - return true; + Location target = getTarget(player); + if (target == null) return true; + RegionSelector selector = session.getRegionSelector(player.getWorld()); + BlockVector3 blockPoint = target.toVector().toBlockPoint(); + if (selector.selectPrimary(blockPoint, ActorSelectorLimits.forActor(player))) { + selector.explainPrimarySelection(player, session, blockPoint); } - return false; + return true; } @Override public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) { - if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) { - Location target = getTarget(player); - if (target == null) return true; - - RegionSelector selector = session.getRegionSelector(player.getWorld()); - BlockVector3 blockPoint = target.toVector().toBlockPoint(); - if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) { - selector.explainSecondarySelection(player, session, blockPoint); - } - return true; + Location target = getTarget(player); + if (target == null) return true; + RegionSelector selector = session.getRegionSelector(player.getWorld()); + BlockVector3 blockPoint = target.toVector().toBlockPoint(); + if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) { + selector.explainSecondarySelection(player, session, blockPoint); } - return false; + return true; } private Location getTarget(Player player) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java index 78f1a5f3e..f2c37e99f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionBlockTool.java @@ -30,6 +30,16 @@ import com.sk89q.worldedit.util.Location; */ public interface DoubleActionBlockTool extends BlockTool { + /** + * Perform the secondary action of this block tool. + * + * @param server + * @param config + * @param player + * @param session + * @param clicked + * @return true to cancel the original event which triggered this action (if possible) + */ boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionTraceTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionTraceTool.java index dde9cca86..1c9b6f83f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionTraceTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DoubleActionTraceTool.java @@ -29,6 +29,15 @@ import com.sk89q.worldedit.extension.platform.Platform; */ public interface DoubleActionTraceTool extends TraceTool { + /** + * Perform the secondary function of this tool. + * + * @param server + * @param config + * @param player + * @param session + * @return true to cancel the original event which triggered this action (if possible) + */ boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java index b60ab4dc1..6c644c35e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/FloatingTreeRemover.java @@ -116,7 +116,7 @@ public class FloatingTreeRemover implements BlockTool { * @param origin any point contained in the floating tree * @return a set containing all blocks in the tree/shroom or null if this is not a floating tree/shroom. */ - private Set bfs(World world, BlockVector3 origin) throws MaxChangedBlocksException { + private Set bfs(World world, BlockVector3 origin) { final Set visited = new HashSet<>(); final LinkedList queue = new LinkedList<>(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java index 27011c5ea..66366f0e3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java @@ -65,7 +65,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo eS.setBlock(pos.toVector().subtract(pos.getDirection()).toBlockPoint(), secondary); } return true; - } catch (MaxChangedBlocksException e) { + } catch (MaxChangedBlocksException ignored) { // one block? eat it } return false; @@ -86,7 +86,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo eS.setBlock(pos.toVector().subtract(pos.getDirection()).toBlockPoint(), primary); } return true; - } catch (MaxChangedBlocksException e) { + } catch (MaxChangedBlocksException ignored) { // one block? eat it } return false; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java new file mode 100644 index 000000000..ca4d12745 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/NavigationWand.java @@ -0,0 +1,68 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.tool; + +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.util.Location; + +public class NavigationWand implements DoubleActionTraceTool { + @Override + public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) { + if (!player.hasPermission("worldedit.navigation.jumpto.tool")) { + return false; + } + final int maxDist = config.navigationWandMaxDistance; + if (maxDist <= 0) { + return false; + } + Location pos = player.getSolidBlockTrace(maxDist); + if (pos != null) { + player.findFreePosition(pos); + } else { + player.printError("No block in sight (or too far)!"); + } + return true; + } + + @Override + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) { + if (!player.hasPermission("worldedit.navigation.thru.tool")) { + return false; + } + final int maxDist = config.navigationWandMaxDistance; + if (maxDist <= 0) { + return false; + } + + if (!player.passThroughForwardWall(Math.max(1, maxDist - 10))) { + player.printError("Nothing to pass through (or too far)!"); + } + return true; + } + + @Override + public boolean canUse(Actor actor) { + return true; // skip check here - checked separately for primary/secondary + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java index ef71569f4..a199b2b7f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/QueryTool.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; @@ -41,7 +42,7 @@ public class QueryTool implements BlockTool { } @Override - public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { World world = (World) clicked.getExtent(); EditSession editSession = session.createEditSession(player); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java index e49a17374..50008bd16 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -52,18 +53,18 @@ public class RecursivePickaxe implements BlockTool { } @Override - public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { World world = (World) clicked.getExtent(); BlockVector3 origin = clicked.toVector().toBlockPoint(); BlockType initialType = world.getBlock(origin).getBlockType(); if (initialType.getMaterial().isAir()) { - return true; + return false; } if (initialType == BlockTypes.BEDROCK && !player.canDestroyBedrock()) { - return true; + return false; } try (EditSession editSession = session.createEditSession(player)) { @@ -96,10 +97,10 @@ public class RecursivePickaxe implements BlockTool { return; } - world.queueBlockBreakEffect(server, pos, initialType, distanceSq); - editSession.setBlock(pos, BlockTypes.AIR.getDefaultState()); + world.queueBlockBreakEffect(server, pos, initialType, distanceSq); + recurse(server, editSession, world, pos.add(1, 0, 0), origin, size, initialType, visited); recurse(server, editSession, world, pos.add(-1, 0, 0), diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java new file mode 100644 index 000000000..43b5f1ea0 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java @@ -0,0 +1,59 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.tool; + +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.util.Location; + +public class SelectionWand implements DoubleActionBlockTool { + + @Override + public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { + RegionSelector selector = session.getRegionSelector(player.getWorld()); + + BlockVector3 blockPoint = clicked.toVector().toBlockPoint(); + if (selector.selectPrimary(blockPoint, ActorSelectorLimits.forActor(player))) { + selector.explainPrimarySelection(player, session, blockPoint); + } + return true; + } + + @Override + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { + RegionSelector selector = session.getRegionSelector(player.getWorld()); + BlockVector3 blockPoint = clicked.toVector().toBlockPoint(); + if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) { + selector.explainSecondarySelection(player, session, blockPoint); + } + return true; + } + + @Override + public boolean canUse(Actor actor) { + return actor.hasPermission("worldedit.selection.pos"); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java index 16721d498..6766528f4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -42,13 +43,12 @@ public class SinglePickaxe implements BlockTool { } @Override - public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { World world = (World) clicked.getExtent(); BlockVector3 blockPoint = clicked.toVector().toBlockPoint(); final BlockType blockType = world.getBlock(blockPoint).getBlockType(); - if (blockType == BlockTypes.BEDROCK - && !player.canDestroyBedrock()) { - return true; + if (blockType == BlockTypes.BEDROCK && !player.canDestroyBedrock()) { + return false; } try (EditSession editSession = session.createEditSession(player)) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TraceTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TraceTool.java index f02801fa5..6f18e2c71 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TraceTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TraceTool.java @@ -26,5 +26,14 @@ import com.sk89q.worldedit.extension.platform.Platform; public interface TraceTool extends Tool { + /** + * Perform the primary action of this trace tool. + * + * @param server + * @param config + * @param player + * @param session + * @return true to cancel the original event which triggered this action (if possible) + */ boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java index 8c353ed74..ec6e16723 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TreeGenerator; @@ -52,8 +53,9 @@ public class TreePlanter implements BlockTool { try { boolean successful = false; + final BlockVector3 pos = clicked.toVector().add(0, 1, 0).toBlockPoint(); for (int i = 0; i < 10; i++) { - if (treeType.generate(editSession, clicked.toVector().add(0, 1, 0).toBlockPoint())) { + if (treeType.generate(editSession, pos)) { successful = true; break; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index f0289957f..36e36914b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -308,78 +308,52 @@ public class PlatformManager { Actor actor = createProxyActor(event.getCause()); Location location = event.getLocation(); - Vector3 vector = location.toVector(); // At this time, only handle interaction from players - if (actor instanceof Player) { - Player player = (Player) actor; - LocalSession session = worldEdit.getSessionManager().get(actor); + if (!(actor instanceof Player)) { + return; + } + Player player = (Player) actor; + LocalSession session = worldEdit.getSessionManager().get(actor); - Request.reset(); - Request.request().setSession(session); - Request.request().setWorld(player.getWorld()); + Request.reset(); + Request.request().setSession(session); + Request.request().setWorld(player.getWorld()); - try { - if (event.getType() == Interaction.HIT) { - if (session.isToolControlEnabled() && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { - if (!actor.hasPermission("worldedit.selection.pos")) { - return; - } - - RegionSelector selector = session.getRegionSelector(player.getWorld()); - - BlockVector3 blockPoint = vector.toBlockPoint(); - if (selector.selectPrimary(blockPoint, ActorSelectorLimits.forActor(player))) { - selector.explainPrimarySelection(actor, session, blockPoint); - } - - event.setCancelled(true); - return; - } - - if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) { - final BlockTool superPickaxe = session.getSuperPickaxe(); - if (superPickaxe != null && superPickaxe.canUse(player)) { - event.setCancelled(superPickaxe.actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location)); - return; - } - } - - Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); - if (tool instanceof DoubleActionBlockTool) { - if (tool.canUse(player)) { - ((DoubleActionBlockTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location); + try { + if (event.getType() == Interaction.HIT) { + // superpickaxe is special because its primary interaction is a left click, not a right click + // in addition, it is implicitly bound to all pickaxe items, not just a single tool item + if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) { + final BlockTool superPickaxe = session.getSuperPickaxe(); + if (superPickaxe != null && superPickaxe.canUse(player)) { + if (superPickaxe.actPrimary(queryCapability(Capability.WORLD_EDITING), + getConfiguration(), player, session, location)) { event.setCancelled(true); } - } - - } else if (event.getType() == Interaction.OPEN) { - if (session.isToolControlEnabled() && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { - if (!actor.hasPermission("worldedit.selection.pos")) { - return; - } - - RegionSelector selector = session.getRegionSelector(player.getWorld()); - BlockVector3 blockPoint = vector.toBlockPoint(); - if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) { - selector.explainSecondarySelection(actor, session, blockPoint); - } - - event.setCancelled(true); return; } - - Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); - if (tool instanceof BlockTool) { - if (tool.canUse(player)) { - ((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location); - event.setCancelled(true); - } - } } - } finally { - Request.reset(); + + Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); + if (tool instanceof DoubleActionBlockTool && tool.canUse(player)) { + if (((DoubleActionBlockTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), + getConfiguration(), player, session, location)) { + event.setCancelled(true); + } + } + + } else if (event.getType() == Interaction.OPEN) { + Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); + if (tool instanceof BlockTool && tool.canUse(player)) { + if (((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), + getConfiguration(), player, session, location)) { + event.setCancelled(true); + } + } } + } finally { + Request.reset(); } } @@ -396,63 +370,26 @@ public class PlatformManager { try { switch (event.getInputType()) { case PRIMARY: { - if (player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().navigationWand)) { - if (getConfiguration().navigationWandMaxDistance <= 0) { - return; - } - - if (!player.hasPermission("worldedit.navigation.jumpto.tool")) { - return; - } - - Location pos = player.getSolidBlockTrace(getConfiguration().navigationWandMaxDistance); - if (pos != null) { - player.findFreePosition(pos); - } else { - player.printError("No block in sight (or too far)!"); - } - - event.setCancelled(true); - return; - } - Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); - if (tool instanceof DoubleActionTraceTool) { - if (tool.canUse(player)) { - ((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session); + if (tool instanceof DoubleActionTraceTool && tool.canUse(player)) { + if (((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), + getConfiguration(), player, session)) { event.setCancelled(true); - return; } + return; } break; } case SECONDARY: { - if (player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().navigationWand)) { - if (getConfiguration().navigationWandMaxDistance <= 0) { - return; - } - - if (!player.hasPermission("worldedit.navigation.thru.tool")) { - return; - } - - if (!player.passThroughForwardWall(40)) { - player.printError("Nothing to pass through!"); - } - - event.setCancelled(true); - return; - } - Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); - if (tool instanceof TraceTool) { - if (tool.canUse(player)) { - ((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session); + if (tool instanceof TraceTool && tool.canUse(player)) { + if (((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), + getConfiguration(), player, session)) { event.setCancelled(true); - return; } + return; } break; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java index ba2468bd0..6b94d94ed 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java @@ -26,6 +26,10 @@ import com.google.common.util.concurrent.MoreExecutors; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.tool.InvalidToolBindException; +import com.sk89q.worldedit.command.tool.NavigationWand; +import com.sk89q.worldedit.command.tool.SelectionWand; +import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; import com.sk89q.worldedit.session.request.Request; @@ -35,6 +39,8 @@ import com.sk89q.worldedit.session.storage.VoidStore; import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.world.gamemode.GameModes; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.item.ItemTypes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,10 +66,12 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class SessionManager { - public static int EXPIRATION_GRACE = 600000; + public static int EXPIRATION_GRACE = 10 * 60 * 1000; private static final int FLUSH_PERIOD = 1000 * 30; private static final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 5)); private static final Logger log = LoggerFactory.getLogger(SessionManager.class); + private static boolean warnedInvalidTool; + private final Timer timer = new Timer(); private final WorldEdit worldEdit; private final Map sessions = new HashMap<>(); @@ -157,6 +165,19 @@ public class SessionManager { session.setConfiguration(config); session.setBlockChangeLimit(config.defaultChangeLimit); session.setTimeout(config.calculationTimeout); + try { + if (owner.hasPermission("worldedit.selection.pos")) { + setDefaultWand(session.getWandItem(), config.wandItem, session, new SelectionWand()); + } + if (owner.hasPermission("worldedit.command.jumpto.tool") || owner.hasPermission("worldedit.command.thru.tool")) { + setDefaultWand(session.getNavWandItem(), config.navigationWand, session, new NavigationWand()); + } + } catch (InvalidToolBindException e) { + if (!warnedInvalidTool) { + warnedInvalidTool = true; + log.warn("Invalid wand tool set in config. Tool will not be assigned: " + e.getItemType()); + } + } // Remember the session regardless of if it's currently active or not. // And have the SessionTracker FLUSH inactive sessions. @@ -188,6 +209,19 @@ public class SessionManager { return false; } + private void setDefaultWand(String sessionItem, String configItem, LocalSession session, Tool wand) throws InvalidToolBindException { + ItemType wandItem = null; + if (sessionItem != null) { + wandItem = ItemTypes.get(sessionItem); + } + if (wandItem == null) { + wandItem = ItemTypes.get(configItem); + } + if (wandItem != null) { + session.setTool(wandItem, wand); + } + } + /** * Save a map of sessions to disk. *