diff --git a/plugin.yml b/plugin.yml index 7018c54fa..5a4a2db9c 100644 --- a/plugin.yml +++ b/plugin.yml @@ -290,6 +290,11 @@ commands: description: Block data cycler tool usage: / permissions: 'worldedit.tool.data-cycler' + floodfill: + description: Flood fill tool + usage: / + aliases: ['flood'] + permissions: 'worldedit.tool.flood-fill' brush: description: Brush tool usage: / diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index ed2bc0671..e02902c94 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -215,7 +215,7 @@ public class EditSession { } if (id != 0) { - if (existing != type && block.getData() > 0 && BlockType.usesData(id)) { + if (BlockType.usesData(id)) { if (fastMode) { world.setBlockDataFast(pt, block.getData()); } else { diff --git a/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java b/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java index 806276af2..cf2be9510 100644 --- a/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/ToolCommands.java @@ -26,6 +26,7 @@ import com.sk89q.minecraft.util.commands.NestedCommand; import com.sk89q.worldedit.*; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.ItemType; +import com.sk89q.worldedit.patterns.Pattern; import com.sk89q.worldedit.tools.*; import com.sk89q.worldedit.util.TreeGenerator; @@ -123,6 +124,32 @@ public class ToolCommands { + ItemType.toHeldName(player.getItemInHand()) + "."); } + @Command( + aliases = {"floodfill", "flood"}, + usage = "", + desc = "Flood fill tool", + min = 2, + max = 2 + ) + @CommandPermissions({"worldedit.tool.flood-fill"}) + public static void floodFill(CommandContext args, WorldEdit we, + LocalSession session, LocalPlayer player, EditSession editSession) + throws WorldEditException { + + LocalConfiguration config = we.getConfiguration(); + int range = args.getInteger(1); + + if (range > config.maxSuperPickaxeSize) { + player.printError("Maximum range: " + config.maxSuperPickaxeSize); + return; + } + + Pattern pattern = we.getBlockPattern(player, args.getString(0)); + session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern)); + player.print("Block flood fill tool bound to " + + ItemType.toHeldName(player.getItemInHand()) + "."); + } + @Command( aliases = {"brush", "br"}, desc = "Brush tool" diff --git a/src/main/java/com/sk89q/worldedit/tools/FloodFillTool.java b/src/main/java/com/sk89q/worldedit/tools/FloodFillTool.java new file mode 100644 index 000000000..64f5d2f52 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/tools/FloodFillTool.java @@ -0,0 +1,118 @@ +// $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 java.util.HashSet; +import java.util.Set; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.patterns.Pattern; + +/** + * A tool that flood fills blocks. + * + * @author sk89q + */ +public class FloodFillTool implements BlockTool { + private int range; + private Pattern pattern; + + public FloodFillTool(int range, Pattern pattern) { + this.range = range; + this.pattern = pattern; + } + + public boolean canUse(LocalPlayer player) { + return player.hasPermission("worldedit.tool.flood-fill"); + } + + public boolean actPrimary(ServerInterface server, LocalConfiguration config, + LocalPlayer player, LocalSession session, WorldVector clicked) { + LocalWorld world = clicked.getWorld(); + + int initialType = world.getBlockType(clicked); + + if (initialType == 0) { + return true; + } + + if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) { + return true; + } + + EditSession editSession = session.createEditSession(player); + + try { + recurse(server, editSession, world, clicked.toBlockVector(), + clicked, range, initialType, new HashSet()); + } 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) + throws MaxChangedBlocksException { + + if (origin.distance(pos) > size || visited.contains(pos)) { + return; + } + + visited.add(pos); + + if (editSession.getBlock(pos).getType() == initialType) { + editSession.setBlock(pos, pattern.next(pos)); + } else { + return; + } + + recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(), + origin, size, initialType, visited); + } + +}