    001package net.minecraft.block;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.List;
    006import java.util.Random;
    007import net.minecraft.block.material.Material;
    008import net.minecraft.entity.Entity;
    009import net.minecraft.util.AxisAlignedBB;
    010import net.minecraft.util.Facing;
    011import net.minecraft.world.IBlockAccess;
    012import net.minecraft.world.World;
    013
    014public abstract class BlockHalfSlab extends Block
    015{
    016    protected final boolean isDoubleSlab;
    017
    018    public BlockHalfSlab(int par1, boolean par2, Material par3Material)
    019    {
    020        super(par1, par3Material);
    021        this.isDoubleSlab = par2;
    022
    023        if (par2)
    024        {
    025            opaqueCubeLookup[par1] = true;
    026        }
    027        else
    028        {
    029            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
    030        }
    031
    032        this.setLightOpacity(255);
    033    }
    034
    035    /**
    036     * Updates the blocks bounds based on its current state. Args: world, x, y, z
    037     */
    038    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    039    {
    040        if (this.isDoubleSlab)
    041        {
    042            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    043        }
    044        else
    045        {
    046            boolean flag = (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) != 0;
    047
    048            if (flag)
    049            {
    050                this.setBlockBounds(0.0F, 0.5F, 0.0F, 1.0F, 1.0F, 1.0F);
    051            }
    052            else
    053            {
    054                this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
    055            }
    056        }
    057    }
    058
    059    /**
    060     * Sets the block's bounds for rendering it as an item
    061     */
    062    public void setBlockBoundsForItemRender()
    063    {
    064        if (this.isDoubleSlab)
    065        {
    066            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    067        }
    068        else
    069        {
    070            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
    071        }
    072    }
    073
    074    /**
    075     * Adds all intersecting collision boxes to a list. (Be sure to only add boxes to the list if they intersect the
    076     * mask.) Parameters: World, X, Y, Z, mask, list, colliding entity
    077     */
    078    public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity)
    079    {
    080        this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
    081        super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
    082    }
    083
    084    /**
    085     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    086     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    087     */
    088    public boolean isOpaqueCube()
    089    {
    090        return this.isDoubleSlab;
    091    }
    092
    093    /**
    094     * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata
    095     */
    096    public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
    097    {
    098        return this.isDoubleSlab ? par9 : (par5 != 0 && (par5 == 1 || (double)par7 <= 0.5D) ? par9 : par9 | 8);
    099    }
    100
    101    /**
    102     * Returns the quantity of items to drop on block destruction.
    103     */
    104    public int quantityDropped(Random par1Random)
    105    {
    106        return this.isDoubleSlab ? 2 : 1;
    107    }
    108
    109    /**
    110     * Determines the damage on the item the block drops. Used in cloth and wood.
    111     */
    112    public int damageDropped(int par1)
    113    {
    114        return par1 & 7;
    115    }
    116
    117    /**
    118     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    119     */
    120    public boolean renderAsNormalBlock()
    121    {
    122        return this.isDoubleSlab;
    123    }
    124
    125    @SideOnly(Side.CLIENT)
    126
    127    /**
    128     * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
    129     * coordinates.  Args: blockAccess, x, y, z, side
    130     */
    131    public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    132    {
    133        if (this.isDoubleSlab)
    134        {
    135            return super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5);
    136        }
    137        else if (par5 != 1 && par5 != 0 && !super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5))
    138        {
    139            return false;
    140        }
    141        else
    142        {
    143            int i1 = par2 + Facing.offsetsXForSide[Facing.oppositeSide[par5]];
    144            int j1 = par3 + Facing.offsetsYForSide[Facing.oppositeSide[par5]];
    145            int k1 = par4 + Facing.offsetsZForSide[Facing.oppositeSide[par5]];
    146            boolean flag = (par1IBlockAccess.getBlockMetadata(i1, j1, k1) & 8) != 0;
    147            return flag ? (par5 == 0 ? true : (par5 == 1 && super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5) ? true : !isBlockSingleSlab(par1IBlockAccess.getBlockId(par2, par3, par4)) || (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 0)) : (par5 == 1 ? true : (par5 == 0 && super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5) ? true : !isBlockSingleSlab(par1IBlockAccess.getBlockId(par2, par3, par4)) || (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) != 0));
    148        }
    149    }
    150
    151    @SideOnly(Side.CLIENT)
    152
    153    /**
    154     * Takes a block ID, returns true if it's the same as the ID for a stone or wooden single slab.
    155     */
    156    private static boolean isBlockSingleSlab(int par0)
    157    {
    158        return par0 == Block.stoneSingleSlab.blockID || par0 == Block.woodSingleSlab.blockID;
    159    }
    160
    161    /**
    162     * Returns the slab block name with step type.
    163     */
    164    public abstract String getFullSlabName(int i);
    165
    166    /**
    167     * Get the block's damage value (for use with pick block).
    168     */
    169    public int getDamageValue(World par1World, int par2, int par3, int par4)
    170    {
    171        return super.getDamageValue(par1World, par2, par3, par4) & 7;
    172    }
    173
    174    @SideOnly(Side.CLIENT)
    175
    176    /**
    177     * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
    178     */
    179    public int idPicked(World par1World, int par2, int par3, int par4)
    180    {
    181        return isBlockSingleSlab(this.blockID) ? this.blockID : (this.blockID == Block.stoneDoubleSlab.blockID ? Block.stoneSingleSlab.blockID : (this.blockID == Block.woodDoubleSlab.blockID ? Block.woodSingleSlab.blockID : Block.stoneSingleSlab.blockID));
    182    }
    183}