001    package net.minecraft.src;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    import java.util.List;
006    import java.util.Random;
007    
008    public class BlockStairs extends Block
009    {
010        private static final int[][] field_72159_a = new int[][] {{2, 6}, {3, 7}, {2, 3}, {6, 7}, {0, 4}, {1, 5}, {0, 1}, {4, 5}};
011    
012        /** The block that is used as model for the stair. */
013        private final Block modelBlock;
014        private final int field_72158_c;
015        private boolean field_72156_cr = false;
016        private int field_72160_cs = 0;
017    
018        protected BlockStairs(int par1, Block par2Block, int par3)
019        {
020            super(par1, par2Block.blockIndexInTexture, par2Block.blockMaterial);
021            this.modelBlock = par2Block;
022            this.field_72158_c = par3;
023            this.setHardness(par2Block.blockHardness);
024            this.setResistance(par2Block.blockResistance / 3.0F);
025            this.setStepSound(par2Block.stepSound);
026            this.setLightOpacity(255);
027            this.setCreativeTab(CreativeTabs.tabBlock);
028        }
029    
030        /**
031         * Updates the blocks bounds based on its current state. Args: world, x, y, z
032         */
033        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
034        {
035            if (this.field_72156_cr)
036            {
037                this.setBlockBounds(0.5F * (float)(this.field_72160_cs % 2), 0.5F * (float)(this.field_72160_cs / 2 % 2), 0.5F * (float)(this.field_72160_cs / 4 % 2), 0.5F + 0.5F * (float)(this.field_72160_cs % 2), 0.5F + 0.5F * (float)(this.field_72160_cs / 2 % 2), 0.5F + 0.5F * (float)(this.field_72160_cs / 4 % 2));
038            }
039            else
040            {
041                this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
042            }
043        }
044    
045        /**
046         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
047         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
048         */
049        public boolean isOpaqueCube()
050        {
051            return false;
052        }
053    
054        /**
055         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
056         */
057        public boolean renderAsNormalBlock()
058        {
059            return false;
060        }
061    
062        /**
063         * The type of render function that is called for this block
064         */
065        public int getRenderType()
066        {
067            return 10;
068        }
069    
070        /**
071         * if the specified block is in the given AABB, add its collision bounding box to the given list
072         */
073        public void addCollidingBlockToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity)
074        {
075            int var8 = par1World.getBlockMetadata(par2, par3, par4);
076            int var9 = var8 & 3;
077            float var10 = 0.0F;
078            float var11 = 0.5F;
079            float var12 = 0.5F;
080            float var13 = 1.0F;
081    
082            if ((var8 & 4) != 0)
083            {
084                var10 = 0.5F;
085                var11 = 1.0F;
086                var12 = 0.0F;
087                var13 = 0.5F;
088            }
089    
090            this.setBlockBounds(0.0F, var10, 0.0F, 1.0F, var11, 1.0F);
091            super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
092    
093            if (var9 == 0)
094            {
095                this.setBlockBounds(0.5F, var12, 0.0F, 1.0F, var13, 1.0F);
096                super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
097            }
098            else if (var9 == 1)
099            {
100                this.setBlockBounds(0.0F, var12, 0.0F, 0.5F, var13, 1.0F);
101                super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
102            }
103            else if (var9 == 2)
104            {
105                this.setBlockBounds(0.0F, var12, 0.5F, 1.0F, var13, 1.0F);
106                super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
107            }
108            else if (var9 == 3)
109            {
110                this.setBlockBounds(0.0F, var12, 0.0F, 1.0F, var13, 0.5F);
111                super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
112            }
113    
114            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
115        }
116    
117        @SideOnly(Side.CLIENT)
118    
119        /**
120         * A randomly called display update to be able to add particles or other items for display
121         */
122        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
123        {
124            this.modelBlock.randomDisplayTick(par1World, par2, par3, par4, par5Random);
125        }
126    
127        /**
128         * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
129         */
130        public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer)
131        {
132            this.modelBlock.onBlockClicked(par1World, par2, par3, par4, par5EntityPlayer);
133        }
134    
135        /**
136         * Called right before the block is destroyed by a player.  Args: world, x, y, z, metaData
137         */
138        public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5)
139        {
140            this.modelBlock.onBlockDestroyedByPlayer(par1World, par2, par3, par4, par5);
141        }
142    
143        @SideOnly(Side.CLIENT)
144    
145        /**
146         * Goes straight to getLightBrightnessForSkyBlocks for Blocks, does some fancy computing for Fluids
147         */
148        public int getMixedBrightnessForBlock(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
149        {
150            return this.modelBlock.getMixedBrightnessForBlock(par1IBlockAccess, par2, par3, par4);
151        }
152    
153        @SideOnly(Side.CLIENT)
154    
155        /**
156         * How bright to render this block based on the light its receiving. Args: iBlockAccess, x, y, z
157         */
158        public float getBlockBrightness(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
159        {
160            return this.modelBlock.getBlockBrightness(par1IBlockAccess, par2, par3, par4);
161        }
162    
163        /**
164         * Returns how much this block can resist explosions from the passed in entity.
165         */
166        public float getExplosionResistance(Entity par1Entity)
167        {
168            return this.modelBlock.getExplosionResistance(par1Entity);
169        }
170    
171        /**
172         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
173         */
174        public int getBlockTextureFromSideAndMetadata(int par1, int par2)
175        {
176            return this.modelBlock.getBlockTextureFromSideAndMetadata(par1, this.field_72158_c);
177        }
178    
179        /**
180         * Returns the block texture based on the side being looked at.  Args: side
181         */
182        public int getBlockTextureFromSide(int par1)
183        {
184            return this.modelBlock.getBlockTextureFromSideAndMetadata(par1, this.field_72158_c);
185        }
186    
187        @SideOnly(Side.CLIENT)
188    
189        /**
190         * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha
191         */
192        public int getRenderBlockPass()
193        {
194            return this.modelBlock.getRenderBlockPass();
195        }
196    
197        /**
198         * How many world ticks before ticking
199         */
200        public int tickRate()
201        {
202            return this.modelBlock.tickRate();
203        }
204    
205        @SideOnly(Side.CLIENT)
206    
207        /**
208         * Returns the bounding box of the wired rectangular prism to render.
209         */
210        public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
211        {
212            return this.modelBlock.getSelectedBoundingBoxFromPool(par1World, par2, par3, par4);
213        }
214    
215        /**
216         * Can add to the passed in vector for a movement vector to be applied to the entity. Args: x, y, z, entity, vec3d
217         */
218        public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3)
219        {
220            this.modelBlock.velocityToAddToEntity(par1World, par2, par3, par4, par5Entity, par6Vec3);
221        }
222    
223        /**
224         * Returns if this block is collidable (only used by Fire). Args: x, y, z
225         */
226        public boolean isCollidable()
227        {
228            return this.modelBlock.isCollidable();
229        }
230    
231        /**
232         * Returns whether this block is collideable based on the arguments passed in Args: blockMetaData, unknownFlag
233         */
234        public boolean canCollideCheck(int par1, boolean par2)
235        {
236            return this.modelBlock.canCollideCheck(par1, par2);
237        }
238    
239        /**
240         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
241         */
242        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
243        {
244            return this.modelBlock.canPlaceBlockAt(par1World, par2, par3, par4);
245        }
246    
247        /**
248         * Called whenever the block is added into the world. Args: world, x, y, z
249         */
250        public void onBlockAdded(World par1World, int par2, int par3, int par4)
251        {
252            this.onNeighborBlockChange(par1World, par2, par3, par4, 0);
253            this.modelBlock.onBlockAdded(par1World, par2, par3, par4);
254        }
255    
256        /**
257         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
258         */
259        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
260        {
261            this.modelBlock.breakBlock(par1World, par2, par3, par4, par5, par6);
262        }
263    
264        /**
265         * Called whenever an entity is walking on top of this block. Args: world, x, y, z, entity
266         */
267        public void onEntityWalking(World par1World, int par2, int par3, int par4, Entity par5Entity)
268        {
269            this.modelBlock.onEntityWalking(par1World, par2, par3, par4, par5Entity);
270        }
271    
272        /**
273         * Ticks the block if it's been scheduled
274         */
275        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
276        {
277            this.modelBlock.updateTick(par1World, par2, par3, par4, par5Random);
278        }
279    
280        /**
281         * Called upon block activation (right click on the block.)
282         */
283        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
284        {
285            return this.modelBlock.onBlockActivated(par1World, par2, par3, par4, par5EntityPlayer, 0, 0.0F, 0.0F, 0.0F);
286        }
287    
288        /**
289         * Called upon the block being destroyed by an explosion
290         */
291        public void onBlockDestroyedByExplosion(World par1World, int par2, int par3, int par4)
292        {
293            this.modelBlock.onBlockDestroyedByExplosion(par1World, par2, par3, par4);
294        }
295    
296        /**
297         * Called when the block is placed in the world.
298         */
299        public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving)
300        {
301            int var6 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
302            int var7 = par1World.getBlockMetadata(par2, par3, par4) & 4;
303    
304            if (var6 == 0)
305            {
306                par1World.setBlockMetadataWithNotify(par2, par3, par4, 2 | var7);
307            }
308    
309            if (var6 == 1)
310            {
311                par1World.setBlockMetadataWithNotify(par2, par3, par4, 1 | var7);
312            }
313    
314            if (var6 == 2)
315            {
316                par1World.setBlockMetadataWithNotify(par2, par3, par4, 3 | var7);
317            }
318    
319            if (var6 == 3)
320            {
321                par1World.setBlockMetadataWithNotify(par2, par3, par4, 0 | var7);
322            }
323        }
324    
325        /**
326         * called before onBlockPlacedBy by ItemBlock and ItemReed
327         */
328        public void updateBlockMetadata(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8)
329        {
330            if (par5 == 0 || par5 != 1 && (double)par7 > 0.5D)
331            {
332                int var9 = par1World.getBlockMetadata(par2, par3, par4);
333                par1World.setBlockMetadataWithNotify(par2, par3, par4, var9 | 4);
334            }
335        }
336    
337        /**
338         * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
339         * x, y, z, startVec, endVec
340         */
341        public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
342        {
343            MovingObjectPosition[] var7 = new MovingObjectPosition[8];
344            int var8 = par1World.getBlockMetadata(par2, par3, par4);
345            int var9 = var8 & 3;
346            boolean var10 = (var8 & 4) == 4;
347            int[] var11 = field_72159_a[var9 + (var10 ? 4 : 0)];
348            this.field_72156_cr = true;
349            int var14;
350            int var15;
351            int var16;
352    
353            for (int var12 = 0; var12 < 8; ++var12)
354            {
355                this.field_72160_cs = var12;
356                int[] var13 = var11;
357                var14 = var11.length;
358    
359                for (var15 = 0; var15 < var14; ++var15)
360                {
361                    var16 = var13[var15];
362    
363                    if (var16 == var12)
364                    {
365                        ;
366                    }
367                }
368    
369                var7[var12] = super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
370            }
371    
372            int[] var21 = var11;
373            int var24 = var11.length;
374    
375            for (var14 = 0; var14 < var24; ++var14)
376            {
377                var15 = var21[var14];
378                var7[var15] = null;
379            }
380    
381            MovingObjectPosition var23 = null;
382            double var22 = 0.0D;
383            MovingObjectPosition[] var25 = var7;
384            var16 = var7.length;
385    
386            for (int var17 = 0; var17 < var16; ++var17)
387            {
388                MovingObjectPosition var18 = var25[var17];
389    
390                if (var18 != null)
391                {
392                    double var19 = var18.hitVec.squareDistanceTo(par6Vec3);
393    
394                    if (var19 > var22)
395                    {
396                        var23 = var18;
397                        var22 = var19;
398                    }
399                }
400            }
401    
402            return var23;
403        }
404    }