diff --git a/src/EditSession.java b/src/EditSession.java index 7e112417d..79b05ca31 100644 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -29,7 +29,9 @@ import java.util.LinkedHashMap; import java.util.Set; import java.util.HashSet; import java.util.Stack; +import java.util.List; import java.util.ArrayList; +import java.util.Collections; import java.util.Random; /** @@ -1751,4 +1753,107 @@ public class EditSession { setBlockIfAir(basePos.add(0, height, 0), leavesBlock); } + + /** + * Count the number of blocks of a list of types in a region. + * + * @param region + * @param searchIDs + * @return + */ + public int countBlocks(Region region, Set searchIDs) { + int count = 0; + + 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); + + if (searchIDs.contains(getBlock(pt).getID())) { + count++; + } + } + } + } + } else { + for (Vector pt : region) { + if (searchIDs.contains(getBlock(pt).getID())) { + count++; + } + } + } + + return count; + } + + /** + * Get the block distribution inside a region. + * + * @param region + * @return + */ + public List> getBlockDistribution(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); + + int id = getBlock(pt).getID(); + + if (map.containsKey(id)) { + map.get(id).increment(); + } else { + Countable c = new Countable(id, 1); + map.put(id, c); + distribution.add(c); + } + } + } + } + } else { + for (Vector pt : region) { + int id = getBlock(pt).getID(); + + if (map.containsKey(id)) { + map.get(id).increment(); + } else { + Countable c = new Countable(id, 1); + map.put(id, c); + } + } + } + + Collections.sort(distribution); + //Collections.reverse(distribution); + + return distribution; + } } diff --git a/src/WorldEditListener.java b/src/WorldEditListener.java index d15e5627e..00cc0e014 100644 --- a/src/WorldEditListener.java +++ b/src/WorldEditListener.java @@ -110,6 +110,8 @@ public class WorldEditListener extends PluginListener { commands.put("/clearhistory", "Clear history"); commands.put("/clearclipboard", "Clear clipboard"); commands.put("//size", "Get size of selected region"); + commands.put("//count", "[BlockIDs] - Count the number of blocks in the region"); + commands.put("//distr", "Get the top block distribution"); commands.put("//set", "[ID] - Set all blocks inside region"); commands.put("//outline", "[ID] - Outline the region with blocks"); commands.put("//walls", "[ID] - Build walls"); @@ -890,6 +892,35 @@ public class WorldEditListener extends PluginListener { player.print("# of blocks: " + region.getSize()); return true; + // Get count + } else if (split[0].equalsIgnoreCase("//count")) { + checkArgs(split, 1, 1, split[0]); + Set searchIDs = getBlockIDs(split[1], true); + player.print("Counted: " + + editSession.countBlocks(session.getRegion(), searchIDs)); + return true; + + // Get block distribution + } else if (split[0].equalsIgnoreCase("//distr")) { + checkArgs(split, 0, 0, split[0]); + List> distribution = + editSession.getBlockDistribution(session.getRegion()); + if (distribution.size() > 0) { // *Should* always be true + int size = session.getRegion().getSize(); + + player.print("# total blocks: " + size); + + for (Countable c : distribution) { + player.print(String.format("%-7s (%.3f%%) %s", + String.valueOf(c.getAmount()), + c.getAmount() / (double)size * 100, + BlockType.fromID(c.getID()).getName())); + } + } else { + player.printError("No blocks counted."); + } + return true; + // Replace all blocks in the region } else if(split[0].equalsIgnoreCase("//set")) { checkArgs(split, 1, 1, split[0]); diff --git a/src/com/sk89q/worldedit/Countable.java b/src/com/sk89q/worldedit/Countable.java index 91918aed8..81082e214 100644 --- a/src/com/sk89q/worldedit/Countable.java +++ b/src/com/sk89q/worldedit/Countable.java @@ -23,7 +23,7 @@ package com.sk89q.worldedit; * * @author sk89q */ -public class Countable { +public class Countable implements Comparable> { /** * ID. */ @@ -71,4 +71,34 @@ public class Countable { public void setAmount(int amount) { this.amount = amount; } + + /** + * Decrement the amount. + */ + public void decrement() { + this.amount--; + } + + /** + * Increment the amount. + */ + public void increment() { + this.amount++; + } + + /** + * Comparison. + * + * @param other + * @return + */ + public int compareTo(Countable other) { + if (amount > other.amount) { + return 1; + } else if (amount == other.amount) { + return 0; + } else { + return -1; + } + } }