package org.mctourney.autoreferee.util; import java.util.Map; import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Colorable; import org.apache.commons.collections.map.DefaultedMap; /** * Represents a type of block, combined with any identifiable metadata. * * @author authorblues */ public class BlockData { // placeholder for a few common block data values public static final BlockData BEDROCK = new BlockData(Material.BEDROCK); public static final BlockData AIR = new BlockData(Material.AIR); private Material mat; /** * Gets the material type. */ public Material getMaterial() { return mat; } /** * Sets the material type. */ public void setMaterial(Material mat) { this.mat = mat; } private byte data; /** * Gets the metadata value. */ public byte getData() { return data; } /** * Sets the metadata value. */ public void setData(byte data) { this.data = data; } /** * Constructs a block data object with a material and metadata. * * @param material material type * @param data metadata value, or -1 if any metadata */ public BlockData(Material material, byte data) { setMaterial(material); setData(data); } /** * Constructs a block data object from an itemstack. */ public BlockData(ItemStack item) { this(item.getType(), item.getData().getData()); } /** * Constructs a block data object with a material and any metadata. * * @param material material type */ public BlockData(Material material) { this(material, (byte)-1); } @Override public int hashCode() { return getMaterial().hashCode(); } @Override public boolean equals(Object o) { // if the object is a mismatched type, its not equal if (o == null || !(o instanceof BlockData)) return false; // otherwise, check that the data is all equivalent BlockData ob = (BlockData) o; return ob.getMaterial().equals(getMaterial()) && this.dataMatches(ob); } private boolean dataMatches(BlockData ob) { return ob.getData() == getData() || ob.getData() == -1 || getData() == -1; } /** * Checks if the specified block matches this block data, taking metadata into account. * * @return true if block matches, otherwise false */ public boolean matchesBlock(Block block) { return block != null && this.equals(BlockData.fromBlock(block)); } public String serialize() { String s = Integer.toString(getMaterial().getId()); return getData() == -1 ? s : (s + "," + Integer.toString(getData())); } /** * Gets a human-readable name for this block data, without color. * * @return block data name */ public String getName() { return ChatColor.stripColor(getDisplayName()); } /** * Gets a human-readable name for this block data. * * @return colored block data name */ public String getDisplayName() { String bname = getMaterial().name().replaceAll("_+", " "); if ((getMaterial().getNewData((byte) 0) instanceof Colorable)) { DyeColor color = DyeColor.getByWoolData(getData()); ChatColor chatColor = ColorConverter.dyeToChat(color); String colorName = color.name().replaceAll("_+", " "); bname = chatColor + colorName + " " + bname + ChatColor.RESET; } return bname; } /** * Unserializes a block data object from a comma-seperated string. * * @param string serialized block data object * @return block data object */ public static BlockData unserialize(String string) { // format: mat[,data] String[] units = string.split(",", 2); try { // parse out the material (and potentially meta-data) Material mat = Material.getMaterial(Integer.parseInt(units[0])); byte data = units.length < 2 ? -1 : Byte.parseByte(units[1]); return new BlockData(mat, data); } // if there is a problem with parsing a material, assume the worst catch (NumberFormatException e) { return null; } } /** * Generates a block data object from a block. * * @param block block object * @return block data object */ public static BlockData fromBlock(Block block) { return new BlockData(block.getType(), block.getData()); } /** * Generates a block data object from an item stack. * * @param item item stack object * @return block data object */ public static BlockData fromItemStack(ItemStack item) { byte b = item.getData().getData(); return new BlockData(item.getType(), b); } /** * Generates a block data object from an inventory. If an inventory contains more than * one type of block, the block of the most quantity is returned. * * @param inv inventory object * @return block data object */ @SuppressWarnings("unchecked") public static BlockData fromInventory(Inventory inv) { Map<BlockData, Integer> count = new DefaultedMap(0); for (ItemStack item : inv) if (item != null) { BlockData bd = BlockData.fromItemStack(item); count.put(bd, item.getAmount() + count.get(bd)); } Map.Entry<BlockData, Integer> best = null; for (Map.Entry<BlockData, Integer> entry : count.entrySet()) if (best == null || entry.getValue() > best.getValue()) best = entry; return best == null ? null : best.getKey(); } }