package com.carpentersblocks.util;
import net.minecraft.block.Block;
import net.minecraft.block.Block.SoundType;
import net.minecraft.block.BlockBreakable;
import net.minecraft.block.BlockPane;
import net.minecraft.block.BlockQuartz;
import net.minecraft.block.BlockRotatedPillar;
import net.minecraft.block.BlockSlab;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.oredict.OreDictionary;
import com.carpentersblocks.CarpentersBlocks;
import com.carpentersblocks.api.IWrappableBlock;
import com.carpentersblocks.block.BlockCoverable;
import com.carpentersblocks.tileentity.TEBase;
import com.carpentersblocks.util.handler.ChatHandler;
import com.carpentersblocks.util.handler.DyeHandler;
import com.carpentersblocks.util.handler.OverlayHandler;
import com.carpentersblocks.util.handler.OverlayHandler.Overlay;
import com.carpentersblocks.util.registry.FeatureRegistry;
public class BlockProperties {
public final static SoundType stepSound = new SoundType(CarpentersBlocks.MODID, 1.0F, 1.0F);
public final static int MASK_DEFAULT_ICON = 0x10;
public static boolean isMetadataDefaultIcon(int metadata)
{
return (metadata & MASK_DEFAULT_ICON) > 0;
}
/**
* Returns {@link TEBase} if one exists and the block at coordinates
* matches passed in {@link Block}.
*
* @param block the {@link Block} to match against
* @param world the {@link World}
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return a {@link TEBase}
*/
public static TEBase getTileEntity(Block block, World world, int x, int y, int z)
{
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity != null && tileEntity instanceof TEBase && world.getBlock(x, y, z).equals(block)) {
return (TEBase) tileEntity;
}
return null;
}
/**
* Adds additional data to unused bits in ItemStack metadata to
* identify special properties for ItemStack.
* <p>
* Tells {@link BlockCoverable} to retrieve block icon rather than
* default blank icon.
*
* @param itemStack
* @param mask
*/
public static void prepareItemStackForRendering(ItemStack itemStack)
{
if (toBlock(itemStack) instanceof BlockCoverable) {
itemStack.setItemDamage(itemStack.getItemDamage() | MASK_DEFAULT_ICON);
}
}
/**
* Checks whether tile entity has attribute.
* <p>
* This checks whether tile entity is null before checking
* attribute to promote code reuse.
*
* @param TE the {@link TEBase} reference
* @param attr the block attribute
* @return <code>true</code> if block has attribute
*/
public static boolean hasAttribute(TEBase TE, byte attr)
{
return TE != null && TE.hasAttribute(attr);
}
/**
* Takes an ItemStack and returns block, or air block if ItemStack
* does not contain a block.
*/
public static Block toBlock(ItemStack itemStack)
{
if (itemStack != null && itemStack.getItem() instanceof ItemBlock) {
return Block.getBlockFromItem(itemStack.getItem());
} else {
return Blocks.air;
}
}
/**
* Returns depth of side cover.
*/
public static float getSideCoverDepth(TEBase TE, int side)
{
if (side == 1 && TE.hasAttribute(TE.ATTR_COVER[side])) {
Block block = toBlock(getCover(TE, side));
if (block.equals(Blocks.snow) || block.equals(Blocks.snow_layer)) {
return 0.125F;
}
}
return 0.0625F;
}
/**
* Returns whether block rotates based on placement conditions.
* The blocks that utilize this property are mostly atypical, and
* must be added manually.
*/
public static boolean blockRotates(ItemStack itemStack)
{
Block block = toBlock(itemStack);
return block instanceof BlockQuartz ||
block instanceof BlockRotatedPillar;
}
/**
* Plays block sound.
* Reduced volume is for damaging a block, versus full volume for placement or destruction.
*/
public static void playBlockSound(World world, ItemStack itemStack, int x, int y, int z, boolean reducedVolume)
{
if (itemStack != null) {
Block block;
if (itemStack.getItem() instanceof ItemBlock) {
block = toBlock(itemStack);
} else {
block = Blocks.sand;
}
SoundType soundType = block.stepSound;
float volume = (soundType.getVolume() + 1.0F) / (reducedVolume ? 8.0F : 2.0F);
float pitch = soundType.getPitch() * 0.8F;
world.playSoundEffect(x + 0.5F, y + 0.5F, z + 0.5F, soundType.func_150496_b(), volume, pitch);
}
}
/**
* Filters the {@link ItemStack} to a form that is safe for standard
* block calls. This is necessary for ItemStacks that contain {@link NBTTagCompounds}
* or otherwise produce a block that has a {@link TileEntity}.
*
* @param itemStack the {@link ItemStack}
* @return an {@link ItemStack} that is safe from throwing casting crashes during {@link Block} calls
*/
public static ItemStack getCallableItemStack(ItemStack itemStack)
{
Block block = toBlock(itemStack);
// IWrappable blocks are assumed safe to return unaltered
if (block instanceof BlockCoverable || block instanceof IWrappableBlock) {
return itemStack;
} else {
return block.hasTileEntity(itemStack.getItemDamage()) ? new ItemStack(Blocks.planks) : itemStack;
}
}
/**
* Returns cover {@link ItemStack}, or instance of {@link BlockCoverable}
* if no cover exists on side.
* <p>
* Note: Side 6 represents the base block.
*
* @param TE the {@link TEBase}
* @param side the side
* @return an {@link ItemStack}
*/
public static ItemStack getCover(TEBase TE, int side)
{
ItemStack itemStack = getCoverSafe(TE, side);
return getCallableItemStack(itemStack);
}
/**
* Returns the cover, or if no cover exists, will return the calling block type.
*
* @param TE the {@link TEBase}
* @param side the side
* @return the {@link ItemStack}
*/
public static ItemStack getCoverSafe(TEBase TE, int side)
{
ItemStack itemStack = TE.getAttribute(TE.ATTR_COVER[side]);
return itemStack != null ? itemStack : new ItemStack(TE.getBlockType());
}
/**
* Returns whether block is a cover.
*/
public static boolean isCover(ItemStack itemStack)
{
if (itemStack.getItem() instanceof ItemBlock && !isOverlay(itemStack)) {
Block block = toBlock(itemStack);
return block.renderAsNormalBlock() ||
block instanceof BlockSlab ||
block instanceof BlockPane ||
block instanceof BlockBreakable ||
FeatureRegistry.coverExceptions.contains(itemStack.getDisplayName()) ||
FeatureRegistry.coverExceptions.contains(ChatHandler.getDefaultTranslation(itemStack));
}
return false;
}
/**
* Checks {@link OreDictionary} to determine if {@link ItemStack} contains
* a dustGlowstone ore name.
*
* @return <code>true</code> if {@link ItemStack} contains dustGlowstone ore name
*/
public static boolean isIlluminator(ItemStack itemStack)
{
if (itemStack != null) {
for (int Id : OreDictionary.getOreIDs(itemStack)) {
if (OreDictionary.getOreName(Id).equals("dustGlowstone")) {
return true;
}
}
}
return false;
}
/**
* Returns true if ItemStack is a dye.
*/
public static boolean isDye(ItemStack itemStack, boolean allowWhite)
{
return itemStack.getItem() != null &&
DyeHandler.isDye(itemStack, allowWhite);
}
/**
* Returns whether ItemStack contains a valid overlay item or block.
*/
public static boolean isOverlay(ItemStack itemStack)
{
return OverlayHandler.overlayMap.containsKey(itemStack.getDisplayName()) ||
OverlayHandler.overlayMap.containsKey(ChatHandler.getDefaultTranslation(itemStack));
}
/**
* Gets the first matching ore dictionary entry from the provided ore names.
*
* @param itemStack the {@link ItemStack}
* @param name the OreDictionary name to check against
* @return the first matching OreDictionary name, otherwise blank string
*/
public static String getOreDictMatch(ItemStack itemStack, String ... name)
{
if (itemStack != null) {
for (int Id : OreDictionary.getOreIDs(itemStack)) {
for (String oreName : name) {
if (OreDictionary.getOreName(Id).equals(oreName)) {
return oreName;
}
}
}
}
return "";
}
/**
* Gets an {@link ItemStack} that best represents the surface
* side of a Carpenter's Block.
* <p>
* The side covers and any overlays are taken into consideration.
*
* @param TE
* @return
*/
public static ItemStack getFeatureSensitiveSideItemStack(TEBase TE, ForgeDirection side)
{
if (side.equals(ForgeDirection.UNKNOWN)) {
return getCover(TE, 6);
}
ItemStack itemStack = null;
int effectiveSide = TE.hasAttribute(TE.ATTR_COVER[side.ordinal()]) ? side.ordinal() : 6;
// Check for overlay
if (TE.hasAttribute(TE.ATTR_OVERLAY[effectiveSide])) {
Overlay overlay = OverlayHandler.getOverlayType(TE.getAttribute(TE.ATTR_OVERLAY[effectiveSide]));
if (OverlayHandler.coversFullSide(overlay, side.ordinal())) {
itemStack = overlay.getItemStack();
}
}
// Check for side cover
if (itemStack == null) {
itemStack = getCover(TE, effectiveSide);
}
return itemStack;
}
}