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.
This commit is contained in:
Wizjany 2013-01-19 09:31:00 -05:00
parent c2154b0f86
commit d78bbc4f68
3 changed files with 193 additions and 34 deletions

View File

@ -20,10 +20,6 @@
package com.sk89q.worldedit; 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.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -32,6 +28,10 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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. * The clipboard remembers the state of a cuboid region.
* *
@ -459,4 +459,43 @@ public class CuboidClipboard {
return distribution; return distribution;
} }
/**
* Get the block distribution inside a clipboard with data values.
*
* @return
*/
// TODO reduce code duplication
public List<Countable<BaseBlock>> getBlockDistributionWithData() {
List<Countable<BaseBlock>> distribution = new ArrayList<Countable<BaseBlock>>();
Map<BaseBlock, Countable<BaseBlock>> map = new HashMap<BaseBlock, Countable<BaseBlock>>();
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<BaseBlock> c = new Countable<BaseBlock>(blk, 1);
map.put(blk, c);
distribution.add(c);
}
}
}
}
Collections.sort(distribution);
// Collections.reverse(distribution);
return distribution;
}
} }

View File

@ -525,16 +525,40 @@ public class EditSession {
return false; return false;
} }
public int countBlock(Region region, Set<Integer> searchIDs) {
Set<BaseBlock> passOn = new HashSet<BaseBlock>();
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. * Count the number of blocks of a list of types in a region.
* *
* @param region * @param region
* @param searchIDs * @param searchBlocks
* @return * @return
*/ */
public int countBlocks(Region region, Set<Integer> searchIDs) { public int countBlocks(Region region, Set<BaseBlock> searchBlocks) {
int count = 0; int count = 0;
// allow -1 data in the searchBlocks to match any type
Set<BaseBlock> newSet = new HashSet<BaseBlock>() {
@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) { if (region instanceof CuboidRegion) {
// Doing this for speed // Doing this for speed
Vector min = region.getMinimumPoint(); Vector min = region.getMinimumPoint();
@ -552,7 +576,8 @@ public class EditSession {
for (int z = minZ; z <= maxZ; ++z) { for (int z = minZ; z <= maxZ; ++z) {
Vector pt = new Vector(x, y, 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; ++count;
} }
} }
@ -560,7 +585,8 @@ public class EditSession {
} }
} else { } else {
for (Vector pt : region) { for (Vector pt : region) {
if (searchIDs.contains(getBlockType(pt))) { BaseBlock compare = new BaseBlock(getBlockType(pt), getBlockData(pt));
if (newSet.contains(compare)) {
++count; ++count;
} }
} }
@ -2671,6 +2697,65 @@ public class EditSession {
return distribution; 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<Countable<BaseBlock>> getBlockDistributionWithData(Region region) {
List<Countable<BaseBlock>> distribution = new ArrayList<Countable<BaseBlock>>();
Map<BaseBlock, Countable<BaseBlock>> map = new HashMap<BaseBlock, Countable<BaseBlock>>();
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<BaseBlock> c = new Countable<BaseBlock>(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<BaseBlock> c = new Countable<BaseBlock>(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 { 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"); final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
expression.optimize(); expression.optimize();
@ -2855,4 +2940,5 @@ public class EditSession {
} }
} // while } // while
} }
} }

View File

@ -41,6 +41,7 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.data.ChunkStore; import com.sk89q.worldedit.data.ChunkStore;
import com.sk89q.worldedit.regions.CuboidRegionSelector; import com.sk89q.worldedit.regions.CuboidRegionSelector;
@ -562,61 +563,94 @@ public class SelectionCommands {
aliases = { "/count" }, aliases = { "/count" },
usage = "<block>", usage = "<block>",
desc = "Counts the number of a certain type of block", desc = "Counts the number of a certain type of block",
flags = "d",
min = 1, min = 1,
max = 1 max = 1
) )
@CommandPermissions("worldedit.analysis.count") @CommandPermissions("worldedit.analysis.count")
public void count(CommandContext args, LocalSession session, LocalPlayer player, public void count(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException { EditSession editSession) throws WorldEditException {
Set<Integer> searchIDs = we.getBlockIDs(player, boolean useData = args.hasFlag('d');
args.getString(0), true); if (args.getString(0).contains(":")) {
player.print("Counted: " + useData = true; //override d flag, if they specified data they want it
editSession.countBlocks(session.getSelection(player.getWorld()), searchIDs)); }
if (useData) {
Set<BaseBlock> searchBlocks = we.getBlocks(player, args.getString(0), true);
int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks);
player.print("Counted: " + count);
} else {
Set<Integer> searchIDs = we.getBlockIDs(player, args.getString(0), true);
int count = editSession.countBlock(session.getSelection(player.getWorld()), searchIDs);
player.print("Counted: " + count);
}
} }
@Command( @Command(
aliases = { "/distr" }, aliases = { "/distr" },
usage = "", usage = "",
desc = "Get the distribution of blocks in the selection", desc = "Get the distribution of blocks in the selection",
help = help =
"Gets the distribution of blocks in the selection.\n" + "Gets the distribution of blocks in the selection.\n" +
"The -c flag gets the distribution of your clipboard.", "The -c flag gets the distribution of your clipboard.\n" +
flags = "c", "The -d flag separates blocks by data",
flags = "cd",
min = 0, min = 0,
max = 0 max = 0
) )
@CommandPermissions("worldedit.analysis.distr") @CommandPermissions("worldedit.analysis.distr")
public void distr(CommandContext args, LocalSession session, LocalPlayer player, public void distr(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException { EditSession editSession) throws WorldEditException {
List<Countable<Integer>> distribution;
int size; int size;
boolean useData = args.hasFlag('d');
List<Countable<Integer>> distribution = null;
List<Countable<BaseBlock>> distributionData = null;
if (args.hasFlag('c')) { if (args.hasFlag('c')) {
CuboidClipboard clip = session.getClipboard(); CuboidClipboard clip = session.getClipboard();
distribution = clip.getBlockDistribution(); if (useData) {
size = clip.getHeight() * clip.getLength() * clip.getWidth(); distributionData = clip.getBlockDistributionWithData();
} else {
distribution = clip.getBlockDistribution();
}
size = clip.getHeight() * clip.getLength() * clip.getWidth();
} else { } else {
distribution = editSession if (useData) {
.getBlockDistribution(session.getSelection(player.getWorld())); distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));
} else {
distribution = editSession.getBlockDistribution(session.getSelection(player.getWorld()));
}
size = session.getSelection(player.getWorld()).getArea(); 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."); player.printError("No blocks counted.");
return; return;
} }
player.print("# total blocks: " + size); player.print("# total blocks: " + size);
for (Countable<Integer> c : distribution) { if (useData) {
BlockType block = BlockType.fromID(c.getID()); for (Countable<BaseBlock> c : distributionData) {
String str = String.format("%-7s (%.3f%%) %s #%d", String name = BlockType.fromID(c.getID().getId()).getName();
String.valueOf(c.getAmount()), String str = String.format("%-7s (%.3f%%) %s #%d:%d",
c.getAmount() / (double) size * 100, String.valueOf(c.getAmount()),
block == null ? "Unknown" : block.getName(), c.getID()); c.getAmount() / (double) size * 100,
player.print(str); name == null ? "Unknown" : name,
c.getID().getType(), c.getID().getData());
player.print(str);
}
} else {
for (Countable<Integer> 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);
}
} }
} }