From d78bbc4f686e70457931d5da232a2871f34d1010 Mon Sep 17 00:00:00 2001 From: Wizjany Date: Sat, 19 Jan 2013 09:31:00 -0500 Subject: [PATCH] Merge Moo0's data flag for distr. Also added data flag to //count. //count -d 35 will now only search for white wool. //count 35:5 will only search for green wool. //count 35 will work as normal. //count 35:-1 will also work. --- .../com/sk89q/worldedit/CuboidClipboard.java | 47 +++++++++- .../java/com/sk89q/worldedit/EditSession.java | 94 ++++++++++++++++++- .../worldedit/commands/SelectionCommands.java | 86 ++++++++++++----- 3 files changed, 193 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/CuboidClipboard.java b/src/main/java/com/sk89q/worldedit/CuboidClipboard.java index 191eb8b3c..d230bfc68 100644 --- a/src/main/java/com/sk89q/worldedit/CuboidClipboard.java +++ b/src/main/java/com/sk89q/worldedit/CuboidClipboard.java @@ -20,10 +20,6 @@ package com.sk89q.worldedit; -import com.sk89q.worldedit.blocks.*; -import com.sk89q.worldedit.data.*; -import com.sk89q.worldedit.schematic.SchematicFormat; - import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -32,6 +28,10 @@ import java.util.List; import java.util.Map; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.data.DataException; +import com.sk89q.worldedit.schematic.SchematicFormat; + /** * The clipboard remembers the state of a cuboid region. * @@ -459,4 +459,43 @@ public List> getBlockDistribution() { return distribution; } + + /** + * Get the block distribution inside a clipboard with data values. + * + * @return + */ + // TODO reduce code duplication + public List> getBlockDistributionWithData() { + List> distribution = new ArrayList>(); + Map> map = new HashMap>(); + + int maxX = getWidth(); + int maxY = getHeight(); + int maxZ = getLength(); + + for (int x = 0; x < maxX; ++x) { + for (int y = 0; y < maxY; ++y) { + for (int z = 0; z < maxZ; ++z) { + + int id = data[x][y][z].getId(); + int meta = data[x][y][z].getData(); + BaseBlock blk = new BaseBlock(id, meta); + + if (map.containsKey(blk)) { + map.get(blk).increment(); + } else { + Countable c = new Countable(blk, 1); + map.put(blk, c); + distribution.add(c); + } + } + } + } + + Collections.sort(distribution); + // Collections.reverse(distribution); + + return distribution; + } } diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index 071655455..e8a78c9da 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -525,16 +525,40 @@ public boolean setChanceBlockIfAir(Vector pos, BaseBlock block, double c) return false; } + public int countBlock(Region region, Set searchIDs) { + Set passOn = new HashSet(); + for (Integer i : searchIDs) { + passOn.add(new BaseBlock(i, -1)); + } + return countBlocks(region, passOn); + } + /** * Count the number of blocks of a list of types in a region. * * @param region - * @param searchIDs + * @param searchBlocks * @return */ - public int countBlocks(Region region, Set searchIDs) { + public int countBlocks(Region region, Set searchBlocks) { int count = 0; + // allow -1 data in the searchBlocks to match any type + Set newSet = new HashSet() { + @Override + public boolean contains(Object o) { + for (BaseBlock b : this.toArray(new BaseBlock[this.size()])) { + if (o instanceof BaseBlock) { + if (b.equalsFuzzy((BaseBlock) o)) { + return true; + } + } + } + return false; + } + }; + newSet.addAll(searchBlocks); + if (region instanceof CuboidRegion) { // Doing this for speed Vector min = region.getMinimumPoint(); @@ -552,7 +576,8 @@ public int countBlocks(Region region, Set searchIDs) { for (int z = minZ; z <= maxZ; ++z) { Vector pt = new Vector(x, y, z); - if (searchIDs.contains(getBlockType(pt))) { + BaseBlock compare = new BaseBlock(getBlockType(pt), getBlockData(pt)); + if (newSet.contains(compare)) { ++count; } } @@ -560,7 +585,8 @@ public int countBlocks(Region region, Set searchIDs) { } } else { for (Vector pt : region) { - if (searchIDs.contains(getBlockType(pt))) { + BaseBlock compare = new BaseBlock(getBlockType(pt), getBlockData(pt)); + if (newSet.contains(compare)) { ++count; } } @@ -2671,6 +2697,65 @@ public List> getBlockDistribution(Region region) { return distribution; } + /** + * Get the block distribution (with data values) inside a region. + * + * @param region + * @return + */ + // TODO reduce code duplication - probably during ops-redux + public List> getBlockDistributionWithData(Region region) { + List> distribution = new ArrayList>(); + Map> map = new HashMap>(); + + if (region instanceof CuboidRegion) { + // Doing this for speed + Vector min = region.getMinimumPoint(); + Vector max = region.getMaximumPoint(); + + int minX = min.getBlockX(); + int minY = min.getBlockY(); + int minZ = min.getBlockZ(); + int maxX = max.getBlockX(); + int maxY = max.getBlockY(); + int maxZ = max.getBlockZ(); + + for (int x = minX; x <= maxX; ++x) { + for (int y = minY; y <= maxY; ++y) { + for (int z = minZ; z <= maxZ; ++z) { + Vector pt = new Vector(x, y, z); + + BaseBlock blk = new BaseBlock(getBlockType(pt), getBlockData(pt)); + + if (map.containsKey(blk)) { + map.get(blk).increment(); + } else { + Countable c = new Countable(blk, 1); + map.put(blk, c); + distribution.add(c); + } + } + } + } + } else { + for (Vector pt : region) { + BaseBlock blk = new BaseBlock(getBlockType(pt), getBlockData(pt)); + + if (map.containsKey(blk)) { + map.get(blk).increment(); + } else { + Countable c = new Countable(blk, 1); + map.put(blk, c); + } + } + } + + Collections.sort(distribution); + // Collections.reverse(distribution); + + return distribution; + } + public int makeShape(final Region region, final Vector zero, final Vector unit, final Pattern pattern, final String expressionString, final boolean hollow) throws ExpressionException, MaxChangedBlocksException { final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data"); expression.optimize(); @@ -2855,4 +2940,5 @@ private void recurseHollow(Region region, BlockVector origin, Set o } } // while } + } diff --git a/src/main/java/com/sk89q/worldedit/commands/SelectionCommands.java b/src/main/java/com/sk89q/worldedit/commands/SelectionCommands.java index 2e5c50a88..1a34ee330 100644 --- a/src/main/java/com/sk89q/worldedit/commands/SelectionCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/SelectionCommands.java @@ -41,6 +41,7 @@ import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.data.ChunkStore; import com.sk89q.worldedit.regions.CuboidRegionSelector; @@ -562,61 +563,94 @@ public void size(CommandContext args, LocalSession session, LocalPlayer player, aliases = { "/count" }, usage = "", desc = "Counts the number of a certain type of block", + flags = "d", min = 1, max = 1 ) @CommandPermissions("worldedit.analysis.count") public void count(CommandContext args, LocalSession session, LocalPlayer player, EditSession editSession) throws WorldEditException { - - Set searchIDs = we.getBlockIDs(player, - args.getString(0), true); - player.print("Counted: " + - editSession.countBlocks(session.getSelection(player.getWorld()), searchIDs)); + + boolean useData = args.hasFlag('d'); + if (args.getString(0).contains(":")) { + useData = true; //override d flag, if they specified data they want it + } + if (useData) { + Set searchBlocks = we.getBlocks(player, args.getString(0), true); + int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks); + player.print("Counted: " + count); + } else { + Set searchIDs = we.getBlockIDs(player, args.getString(0), true); + int count = editSession.countBlock(session.getSelection(player.getWorld()), searchIDs); + player.print("Counted: " + count); + } } @Command( aliases = { "/distr" }, usage = "", - desc = "Get the distribution of blocks in the selection", + desc = "Get the distribution of blocks in the selection", help = "Gets the distribution of blocks in the selection.\n" + - "The -c flag gets the distribution of your clipboard.", - flags = "c", + "The -c flag gets the distribution of your clipboard.\n" + + "The -d flag separates blocks by data", + flags = "cd", min = 0, max = 0 ) - @CommandPermissions("worldedit.analysis.distr") + @CommandPermissions("worldedit.analysis.distr") public void distr(CommandContext args, LocalSession session, LocalPlayer player, EditSession editSession) throws WorldEditException { - - List> distribution; + int size; - + boolean useData = args.hasFlag('d'); + List> distribution = null; + List> distributionData = null; + if (args.hasFlag('c')) { CuboidClipboard clip = session.getClipboard(); - distribution = clip.getBlockDistribution(); - size = clip.getHeight() * clip.getLength() * clip.getWidth(); + if (useData) { + distributionData = clip.getBlockDistributionWithData(); + } else { + distribution = clip.getBlockDistribution(); + } + size = clip.getHeight() * clip.getLength() * clip.getWidth(); } else { - distribution = editSession - .getBlockDistribution(session.getSelection(player.getWorld())); + if (useData) { + distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld())); + } else { + distribution = editSession.getBlockDistribution(session.getSelection(player.getWorld())); + } size = session.getSelection(player.getWorld()).getArea(); } - - if (distribution.size() <= 0) { // *Should* always be true + + if ((useData && distributionData.size() <= 0) + || (!useData && distribution.size() <= 0)) { // *Should* always be false player.printError("No blocks counted."); return; } - + player.print("# total blocks: " + size); - for (Countable c : distribution) { - BlockType block = BlockType.fromID(c.getID()); - String str = String.format("%-7s (%.3f%%) %s #%d", - String.valueOf(c.getAmount()), - c.getAmount() / (double) size * 100, - block == null ? "Unknown" : block.getName(), c.getID()); - player.print(str); + if (useData) { + for (Countable c : distributionData) { + String name = BlockType.fromID(c.getID().getId()).getName(); + String str = String.format("%-7s (%.3f%%) %s #%d:%d", + String.valueOf(c.getAmount()), + c.getAmount() / (double) size * 100, + name == null ? "Unknown" : name, + c.getID().getType(), c.getID().getData()); + player.print(str); + } + } else { + for (Countable c : distribution) { + BlockType block = BlockType.fromID(c.getID()); + String str = String.format("%-7s (%.3f%%) %s #%d", + String.valueOf(c.getAmount()), + c.getAmount() / (double) size * 100, + block == null ? "Unknown" : block.getName(), c.getID()); + player.print(str); + } } }