001    package net.minecraft.block;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.List;
006    import java.util.Random;
007    import net.minecraft.block.material.Material;
008    import net.minecraft.entity.Entity;
009    import net.minecraft.util.AxisAlignedBB;
010    import net.minecraft.util.Facing;
011    import net.minecraft.world.IBlockAccess;
012    import net.minecraft.world.World;
013    
014    public abstract class BlockHalfSlab extends Block
015    {
016        private final boolean isDoubleSlab;
017    
018        public BlockHalfSlab(int par1, boolean par2, Material par3Material)
019        {
020            super(par1, 6, 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 var5 = (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) != 0;
047    
048                if (var5)
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         * if the specified block is in the given AABB, add its collision bounding box to the given list
076         */
077        public void addCollidingBlockToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity)
078        {
079            this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
080            super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
081        }
082    
083        /**
084         * Returns the block texture based on the side being looked at.  Args: side
085         */
086        public int getBlockTextureFromSide(int par1)
087        {
088            return this.getBlockTextureFromSideAndMetadata(par1, 0);
089        }
090    
091        /**
092         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
093         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
094         */
095        public boolean isOpaqueCube()
096        {
097            return this.isDoubleSlab;
098        }
099    
100        /**
101         * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata
102         */
103        public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
104        {
105            return this.isDoubleSlab ? par9 : (par5 != 0 && (par5 == 1 || (double)par7 <= 0.5D) ? par9 : par9 | 8);
106        }
107    
108        /**
109         * Returns the quantity of items to drop on block destruction.
110         */
111        public int quantityDropped(Random par1Random)
112        {
113            return this.isDoubleSlab ? 2 : 1;
114        }
115    
116        /**
117         * Determines the damage on the item the block drops. Used in cloth and wood.
118         */
119        public int damageDropped(int par1)
120        {
121            return par1 & 7;
122        }
123    
124        /**
125         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
126         */
127        public boolean renderAsNormalBlock()
128        {
129            return this.isDoubleSlab;
130        }
131    
132        @SideOnly(Side.CLIENT)
133    
134        /**
135         * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
136         * coordinates.  Args: blockAccess, x, y, z, side
137         */
138        public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
139        {
140            if (this.isDoubleSlab)
141            {
142                return super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5);
143            }
144            else if (par5 != 1 && par5 != 0 && !super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5))
145            {
146                return false;
147            }
148            else
149            {
150                int var6 = par2 + Facing.offsetsXForSide[Facing.faceToSide[par5]];
151                int var7 = par3 + Facing.offsetsYForSide[Facing.faceToSide[par5]];
152                int var8 = par4 + Facing.offsetsZForSide[Facing.faceToSide[par5]];
153                boolean var9 = (par1IBlockAccess.getBlockMetadata(var6, var7, var8) & 8) != 0;
154                return var9 ? (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));
155            }
156        }
157    
158        @SideOnly(Side.CLIENT)
159    
160        /**
161         * Takes a block ID, returns true if it's the same as the ID for a stone or wooden single slab.
162         */
163        private static boolean isBlockSingleSlab(int par0)
164        {
165            return par0 == Block.stoneSingleSlab.blockID || par0 == Block.woodSingleSlab.blockID;
166        }
167    
168        /**
169         * Returns the slab block name with step type.
170         */
171        public abstract String getFullSlabName(int var1);
172    
173        /**
174         * Get the block's damage value (for use with pick block).
175         */
176        public int getDamageValue(World par1World, int par2, int par3, int par4)
177        {
178            return super.getDamageValue(par1World, par2, par3, par4) & 7;
179        }
180    
181        @SideOnly(Side.CLIENT)
182    
183        /**
184         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
185         */
186        public int idPicked(World par1World, int par2, int par3, int par4)
187        {
188            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));
189        }
190    }