package com.bergerkiller.bukkit.common.utils; import net.minecraft.server.Item; import org.bukkit.Material; import org.bukkit.TreeSpecies; import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Attachable; import org.bukkit.material.MaterialData; import com.bergerkiller.bukkit.common.MaterialBooleanProperty; import com.bergerkiller.bukkit.common.MaterialProperty; import com.bergerkiller.bukkit.common.MaterialTypeProperty; import com.bergerkiller.bukkit.common.internal.CommonNMS; import com.bergerkiller.bukkit.common.wrappers.BlockInfo; /** * Contains material properties and helper functions */ public class MaterialUtil { /* * The below methods may have to be manually re-designed when * material IDs/Data officially become 'erased'. * But we know how Minecraft is addicted to them, so I bet they * still end up somewhere. Since they are valuable for fast equality * checks and thus mapping values to item materials/data, these methods * will stay, unless the default implementation has an equivalent such as * a UUID. Name mapping is NOT an option! * * That said, for future compatibility, redirect all method calls to these * methods. */ @SuppressWarnings("deprecation") public static Material getType(int typeId) { return Material.getMaterial(typeId); } @SuppressWarnings("deprecation") public static int getTypeId(ItemStack item) { return item.getTypeId(); } @SuppressWarnings("deprecation") public static int getTypeId(org.bukkit.block.Block block) { return block.getTypeId(); } @SuppressWarnings("deprecation") public static int getTypeId(Material material) { return material == null ? 0 : material.getId(); } @SuppressWarnings("deprecation") public static int getRawData(TreeSpecies treeSpecies) { return treeSpecies.getData(); } @SuppressWarnings("deprecation") public static int getRawData(org.bukkit.block.Block block) { return block.getData(); } public static int getRawData(ItemStack item) { return item.getDurability(); } @SuppressWarnings("deprecation") public static int getRawData(MaterialData materialData) { return materialData.getData(); } /** * Obtains the Material Data using the material type Id and data value specified. * <b>Please use the int data version instead, as Block data is expected to become * more than a byte!</b> * * @param typeId of the material * @param data for the material * @return new MaterialData instance for this type of material and data */ public static MaterialData getData(int typeId, byte data) { return getData(typeId, (int) data); } /** * Obtains the Material Data using the material type Id and data value specified * * @param typeId of the material * @param rawData for the material * @return new MaterialData instance for this type of material and data */ @SuppressWarnings("deprecation") public static MaterialData getData(int typeId, int rawData) { Material type = Material.getMaterial(typeId); return type == null ? new MaterialData(typeId, (byte) rawData) : getData(type, rawData); } /** * Obtains the Material Data using the material type Id and data value specified * * @param type of the material * @param rawData for the material * @return new MaterialData instance for this type of material and data */ @SuppressWarnings("deprecation") public static MaterialData getData(Material type, int rawData) { if (type == null) { return new MaterialData(0, (byte) rawData); } final MaterialData mdata = type.getNewData((byte) rawData); // Fix attachable face returning NULL sometimes if (mdata instanceof Attachable) { Attachable att = (Attachable) mdata; if (att.getAttachedFace() == null) { att.setFacingDirection(BlockFace.NORTH); } } return mdata; } /** * Checks whether the material Id is contained in the types * * @param material to check * @param types to look in * @return True if the material is contained */ public static boolean isType(int material, int... types) { return LogicUtil.containsInt(material, types); } /** * Checks whether the material of the item is contained in the types * * @param itemStack containing the material type to check * @param types to look in * @return True if the material is contained */ public static boolean isType(ItemStack itemStack, Material... types) { return isType(getTypeId(itemStack), types); } /** * Checks whether the material is contained in the types * * @param material to check * @param types to look in * @return True if the material is contained */ public static boolean isType(Material material, Material... types) { return LogicUtil.contains(material, types); } /** * Checks whether the material Id is contained in the types * * @param material to check * @param types to look in * @return True if the material is contained */ public static boolean isType(int material, Material... types) { for (Material type : types) { if (getTypeId(type) == material) { return true; } } return false; } /** * Checks whether the material of a block is contained in the types * * @param block to compare the types with * @param types to look in * @return True if the material is contained */ public static boolean isType(org.bukkit.block.Block block, Material... types) { return isType(getTypeId(block), types); } /** * Checks whether the material of a block is contained in the types * * @param block to compare the types with * @param types to look in * @return True if the material is contained */ public static boolean isType(org.bukkit.block.Block block, int... types) { return isType(getTypeId(block), types); } /** * Gets the damage resilience of a block to damage dealt by a certain entity * * @param blockId of the block * @param source of the damage * @return resilience */ @Deprecated public static float getDamageResilience(int blockId, Entity source) { return BlockInfo.get(blockId).getDamageResilience(source); } /** * The material is a type of door (iron or wooden door) */ public static final MaterialTypeProperty ISDOOR = new MaterialTypeProperty(Material.WOOD_DOOR, Material.IRON_DOOR); /** * The material is a type of piston base */ public static final MaterialTypeProperty ISPISTONBASE = new MaterialTypeProperty(Material.PISTON_BASE, Material.PISTON_STICKY_BASE); /** * The material is a type of redstone torch */ public static final MaterialTypeProperty ISREDSTONETORCH = new MaterialTypeProperty(Material.REDSTONE_TORCH_OFF, Material.REDSTONE_TORCH_ON); /** * The material is a type of diode (item type excluded) */ public static final MaterialTypeProperty ISDIODE = new MaterialTypeProperty(Material.DIODE_BLOCK_OFF, Material.DIODE_BLOCK_ON); /** * The material is a type of comparator (item type excluded) */ public static final MaterialTypeProperty ISCOMPARATOR = new MaterialTypeProperty(Material.REDSTONE_COMPARATOR_OFF, Material.REDSTONE_COMPARATOR_ON); /** * The material is a type of bucket (milk bucket is excluded) */ public static final MaterialTypeProperty ISBUCKET = new MaterialTypeProperty(Material.WATER_BUCKET, Material.LAVA_BUCKET, Material.BUCKET); /** * The material is a type of rails */ public static final MaterialTypeProperty ISRAILS = new MaterialTypeProperty(Material.RAILS, Material.POWERED_RAIL, Material.DETECTOR_RAIL, Material.ACTIVATOR_RAIL); /** * The material is a type of sign (item type is excluded) */ public static final MaterialTypeProperty ISSIGN = new MaterialTypeProperty(Material.WALL_SIGN, Material.SIGN_POST); /** * The material is a type of pressure plate */ public static final MaterialTypeProperty ISPRESSUREPLATE = new MaterialTypeProperty(Material.WOOD_PLATE, Material.STONE_PLATE, Material.IRON_PLATE, Material.GOLD_PLATE); /** * The material is a type of Minecart item */ public static final MaterialTypeProperty ISMINECART = new MaterialTypeProperty(Material.MINECART, Material.POWERED_MINECART, Material.STORAGE_MINECART, Material.EXPLOSIVE_MINECART, Material.HOPPER_MINECART); /** * The material is a type of wieldable sword */ public static final MaterialTypeProperty ISSWORD = new MaterialTypeProperty(Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.IRON_SWORD, Material.DIAMOND_SWORD); /** * The material is a type of wearable boots */ public static final MaterialTypeProperty ISBOOTS = new MaterialTypeProperty(Material.LEATHER_BOOTS, Material.IRON_BOOTS, Material.GOLD_BOOTS, Material.DIAMOND_BOOTS, Material.CHAINMAIL_BOOTS); /** * The material is a type of wearable leggings */ public static final MaterialTypeProperty ISLEGGINGS = new MaterialTypeProperty(Material.LEATHER_LEGGINGS, Material.IRON_LEGGINGS, Material.GOLD_LEGGINGS, Material.DIAMOND_LEGGINGS, Material.CHAINMAIL_LEGGINGS); /** * The material is a type of wearable chestplate */ public static final MaterialTypeProperty ISCHESTPLATE = new MaterialTypeProperty(Material.LEATHER_CHESTPLATE, Material.IRON_CHESTPLATE, Material.GOLD_CHESTPLATE, Material.DIAMOND_CHESTPLATE, Material.CHAINMAIL_CHESTPLATE); /** * The material is a type of wearable helmet */ public static final MaterialTypeProperty ISHELMET = new MaterialTypeProperty(Material.LEATHER_HELMET, Material.IRON_HELMET, Material.GOLD_HELMET, Material.DIAMOND_HELMET, Material.CHAINMAIL_HELMET); /** * The material is a type of armor */ public static final MaterialTypeProperty ISARMOR = new MaterialTypeProperty(ISBOOTS, ISLEGGINGS, ISCHESTPLATE, ISHELMET); /** * The material can be interacted with, such as buttons and levers. * Materials of this type suppress block placement upon interaction. */ public static final MaterialTypeProperty ISINTERACTABLE = new MaterialTypeProperty(Material.LEVER, Material.WOOD_DOOR, Material.IRON_DOOR, Material.TRAP_DOOR, Material.CHEST, Material.HOPPER, Material.DROPPER, Material.ENDER_CHEST, Material.FURNACE, Material.BURNING_FURNACE, Material.DISPENSER, Material.WORKBENCH, Material.DIODE_BLOCK_ON, Material.DIODE_BLOCK_OFF, Material.BED, Material.CAKE, Material.NOTE_BLOCK, Material.JUKEBOX, Material.WOOD_BUTTON, Material.STONE_BUTTON, Material.REDSTONE_COMPARATOR_OFF, Material.REDSTONE_COMPARATOR_ON, Material.ANVIL, Material.FENCE_GATE); /** * The material causes suffocation to entities inside */ public static final MaterialProperty<Boolean> SUFFOCATES = new MaterialBooleanProperty() { @Override public Boolean get(Material type) { return BlockInfo.get(type).isSuffocating(); } }; /** * The material is a type of heatable item that can be crafted using a furnace */ public static final MaterialProperty<Boolean> ISHEATABLE = new MaterialBooleanProperty() { @Override public Boolean get(Material type) { return RecipeUtil.isHeatableItem(type); } }; /** * The material is a type of fuel that can be burned in a furnace */ public static final MaterialProperty<Boolean> ISFUEL = new MaterialBooleanProperty() { @Override public Boolean get(Material type) { return RecipeUtil.isFuelItem(type); } }; /** * The material is a solid block that lets no light through and on which other blocks can be placed */ public static final MaterialProperty<Boolean> ISSOLID = new MaterialBooleanProperty() { @Override public Boolean get(Material type) { return BlockInfo.get(type).isSolid(); } }; /** * The material can supply redstone power and redstone wire connects to it */ public static final MaterialProperty<Boolean> ISPOWERSOURCE = new MaterialBooleanProperty() { @Override public Boolean get(Material type) { return BlockInfo.get(type).isPowerSource(); } }; /** * The material has a data value that further defines the type of Item or Block */ public static final MaterialProperty<Boolean> HASDATA = new MaterialBooleanProperty() { @Override public Boolean get(Material type) { final Item item = CommonNMS.getItem(type); return item == null ? false : item.n(); } }; /** * Gets the amount of light a block material emits */ public static final MaterialProperty<Integer> EMISSION = new MaterialProperty<Integer>() { @Override public Integer get(Material type) { return BlockInfo.get(type).getLightEmission(); } }; /** * Gets the opacity of a block material */ public static final MaterialProperty<Integer> OPACITY = new MaterialProperty<Integer>() { @Override public Integer get(Material type) { return BlockInfo.get(type).getOpacity(); } }; }