package tc.oc.commons.bukkit.util; import java.util.Iterator; import gnu.trove.impl.Constants; import gnu.trove.iterator.TIntIntIterator; import gnu.trove.iterator.TIntIterator; import gnu.trove.map.TIntIntMap; import gnu.trove.map.hash.TIntIntHashMap; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.material.MaterialData; import org.bukkit.util.BlockVector; import static tc.oc.commons.bukkit.util.MaterialUtils.decodeMaterial; import static tc.oc.commons.bukkit.util.MaterialUtils.encodeMaterial; /** * Efficiently counts distinct {@link MaterialData}s */ public class MaterialCounter { private final TIntIntMap counts; private MaterialCounter(TIntIntMap counts) { this.counts = counts; } public MaterialCounter() { this(new TIntIntHashMap(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, -1, 0)); } public MaterialCounter(MaterialCounter other) { this(new TIntIntHashMap(other.counts)); } public boolean contains(int encodedMaterial) { return counts.containsKey(encodedMaterial); } public boolean contains(int typeId, byte metadata) { return contains(encodeMaterial(typeId, metadata)); } public boolean contains(MaterialData material) { return contains(encodeMaterial(material)); } public int get(int encodedMaterial) { return counts.get(encodedMaterial); } public int get(int typeId, byte metadata) { return get(encodeMaterial(typeId, metadata)); } public int get(MaterialData material) { return get(encodeMaterial(material)); } public int increment(int encodedMaterial, int count) { return counts.adjustOrPutValue(encodedMaterial, count, count); } public int increment(int typeId, byte metadata, int count) { return increment(encodeMaterial(typeId, metadata), count); } public int increment(MaterialData material, int count) { return increment(encodeMaterial(material), count); } public int increment(BlockState block, int count) { return increment(encodeMaterial(block), count); } public int analyze(World world, BlockVector pos) { return increment(encodeMaterial(world, pos), 1); } public int analyze(Location location) { return increment(encodeMaterial(location), 1); } public int analyze(Block block) { return increment(encodeMaterial(block), 1); } public int analyze(BlockState block) { return increment(encodeMaterial(block), 1); } public void analyze(World world, Iterator<BlockVector> blocks) { while(blocks.hasNext()) { analyze(world, blocks.next()); } } public void clear() { counts.clear(); } public void addAll(MaterialCounter other) { for(TIntIntIterator iter = other.counts.iterator(); iter.hasNext();) { iter.advance(); counts.adjustOrPutValue(iter.key(), iter.value(), iter.value()); } } public Iterable<MaterialData> materials() { return new Iterable<MaterialData>() { @Override public Iterator<MaterialData> iterator() { return new Iterator<MaterialData>() { final TIntIterator iter = counts.keySet().iterator(); @Override public boolean hasNext() { return iter.hasNext(); } @Override public MaterialData next() { return decodeMaterial(iter.next()); } @Override public void remove() { iter.remove(); } }; } }; } }