001    package net.minecraft.block;
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    import net.minecraft.creativetab.CreativeTabs;
008    import net.minecraft.entity.Entity;
009    import net.minecraft.entity.EntityLiving;
010    import net.minecraft.entity.player.EntityPlayer;
011    import net.minecraft.util.AxisAlignedBB;
012    import net.minecraft.util.MathHelper;
013    import net.minecraft.util.MovingObjectPosition;
014    import net.minecraft.util.Vec3;
015    import net.minecraft.world.IBlockAccess;
016    import net.minecraft.world.World;
017    
018    public class BlockStairs extends Block
019    {
020        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}};
021        private static final int[] field_82545_b = new int[] {1, -1, 0, 0};
022        private static final int[] field_82546_c = new int[] {0, 0, 1, -1};
023    
024        /** The block that is used as model for the stair. */
025        private final Block modelBlock;
026        private final int field_72158_c;
027        private boolean field_72156_cr = false;
028        private int field_72160_cs = 0;
029    
030        protected BlockStairs(int par1, Block par2Block, int par3)
031        {
032            super(par1, par2Block.blockIndexInTexture, par2Block.blockMaterial);
033            this.modelBlock = par2Block;
034            this.field_72158_c = par3;
035            this.setHardness(par2Block.blockHardness);
036            this.setResistance(par2Block.blockResistance / 3.0F);
037            this.setStepSound(par2Block.stepSound);
038            this.setLightOpacity(255);
039            this.setCreativeTab(CreativeTabs.tabBlock);
040        }
041    
042        /**
043         * Updates the blocks bounds based on its current state. Args: world, x, y, z
044         */
045        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
046        {
047            if (this.field_72156_cr)
048            {
049                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));
050            }
051            else
052            {
053                this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
054            }
055        }
056    
057        /**
058         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
059         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
060         */
061        public boolean isOpaqueCube()
062        {
063            return false;
064        }
065    
066        /**
067         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
068         */
069        public boolean renderAsNormalBlock()
070        {
071            return false;
072        }
073    
074        /**
075         * The type of render function that is called for this block
076         */
077        public int getRenderType()
078        {
079            return 10;
080        }
081    
082        public void func_82541_d(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
083        {
084            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
085    
086            if ((var5 & 4) != 0)
087            {
088                this.setBlockBounds(0.0F, 0.5F, 0.0F, 1.0F, 1.0F, 1.0F);
089            }
090            else
091            {
092                this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
093            }
094        }
095    
096        public static boolean func_82543_e(int par0)
097        {
098            return par0 > 0 && Block.blocksList[par0] instanceof BlockStairs;
099        }
100    
101        private boolean func_82540_f(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
102        {
103            int var6 = par1IBlockAccess.getBlockId(par2, par3, par4);
104            return func_82543_e(var6) && par1IBlockAccess.getBlockMetadata(par2, par3, par4) == par5;
105        }
106    
107        public boolean func_82542_g(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
108        {
109            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
110            int var6 = var5 & 3;
111            float var7 = 0.5F;
112            float var8 = 1.0F;
113    
114            if ((var5 & 4) != 0)
115            {
116                var7 = 0.0F;
117                var8 = 0.5F;
118            }
119    
120            float var9 = 0.0F;
121            float var10 = 1.0F;
122            float var11 = 0.0F;
123            float var12 = 0.5F;
124            boolean var13 = true;
125            int var14;
126            int var15;
127            int var16;
128    
129            if (var6 == 0)
130            {
131                var9 = 0.5F;
132                var12 = 1.0F;
133                var14 = par1IBlockAccess.getBlockId(par2 + 1, par3, par4);
134                var15 = par1IBlockAccess.getBlockMetadata(par2 + 1, par3, par4);
135    
136                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
137                {
138                    var16 = var15 & 3;
139    
140                    if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5))
141                    {
142                        var12 = 0.5F;
143                        var13 = false;
144                    }
145                    else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5))
146                    {
147                        var11 = 0.5F;
148                        var13 = false;
149                    }
150                }
151            }
152            else if (var6 == 1)
153            {
154                var10 = 0.5F;
155                var12 = 1.0F;
156                var14 = par1IBlockAccess.getBlockId(par2 - 1, par3, par4);
157                var15 = par1IBlockAccess.getBlockMetadata(par2 - 1, par3, par4);
158    
159                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
160                {
161                    var16 = var15 & 3;
162    
163                    if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5))
164                    {
165                        var12 = 0.5F;
166                        var13 = false;
167                    }
168                    else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5))
169                    {
170                        var11 = 0.5F;
171                        var13 = false;
172                    }
173                }
174            }
175            else if (var6 == 2)
176            {
177                var11 = 0.5F;
178                var12 = 1.0F;
179                var14 = par1IBlockAccess.getBlockId(par2, par3, par4 + 1);
180                var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 + 1);
181    
182                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
183                {
184                    var16 = var15 & 3;
185    
186                    if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5))
187                    {
188                        var10 = 0.5F;
189                        var13 = false;
190                    }
191                    else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5))
192                    {
193                        var9 = 0.5F;
194                        var13 = false;
195                    }
196                }
197            }
198            else if (var6 == 3)
199            {
200                var14 = par1IBlockAccess.getBlockId(par2, par3, par4 - 1);
201                var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 - 1);
202    
203                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
204                {
205                    var16 = var15 & 3;
206    
207                    if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5))
208                    {
209                        var10 = 0.5F;
210                        var13 = false;
211                    }
212                    else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5))
213                    {
214                        var9 = 0.5F;
215                        var13 = false;
216                    }
217                }
218            }
219    
220            this.setBlockBounds(var9, var7, var11, var10, var8, var12);
221            return var13;
222        }
223    
224        public boolean func_82544_h(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
225        {
226            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
227            int var6 = var5 & 3;
228            float var7 = 0.5F;
229            float var8 = 1.0F;
230    
231            if ((var5 & 4) != 0)
232            {
233                var7 = 0.0F;
234                var8 = 0.5F;
235            }
236    
237            float var9 = 0.0F;
238            float var10 = 0.5F;
239            float var11 = 0.5F;
240            float var12 = 1.0F;
241            boolean var13 = false;
242            int var14;
243            int var15;
244            int var16;
245    
246            if (var6 == 0)
247            {
248                var14 = par1IBlockAccess.getBlockId(par2 - 1, par3, par4);
249                var15 = par1IBlockAccess.getBlockMetadata(par2 - 1, par3, par4);
250    
251                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
252                {
253                    var16 = var15 & 3;
254    
255                    if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5))
256                    {
257                        var11 = 0.0F;
258                        var12 = 0.5F;
259                        var13 = true;
260                    }
261                    else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5))
262                    {
263                        var11 = 0.5F;
264                        var12 = 1.0F;
265                        var13 = true;
266                    }
267                }
268            }
269            else if (var6 == 1)
270            {
271                var14 = par1IBlockAccess.getBlockId(par2 + 1, par3, par4);
272                var15 = par1IBlockAccess.getBlockMetadata(par2 + 1, par3, par4);
273    
274                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
275                {
276                    var9 = 0.5F;
277                    var10 = 1.0F;
278                    var16 = var15 & 3;
279    
280                    if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5))
281                    {
282                        var11 = 0.0F;
283                        var12 = 0.5F;
284                        var13 = true;
285                    }
286                    else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5))
287                    {
288                        var11 = 0.5F;
289                        var12 = 1.0F;
290                        var13 = true;
291                    }
292                }
293            }
294            else if (var6 == 2)
295            {
296                var14 = par1IBlockAccess.getBlockId(par2, par3, par4 - 1);
297                var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 - 1);
298    
299                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
300                {
301                    var11 = 0.0F;
302                    var12 = 0.5F;
303                    var16 = var15 & 3;
304    
305                    if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5))
306                    {
307                        var13 = true;
308                    }
309                    else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5))
310                    {
311                        var9 = 0.5F;
312                        var10 = 1.0F;
313                        var13 = true;
314                    }
315                }
316            }
317            else if (var6 == 3)
318            {
319                var14 = par1IBlockAccess.getBlockId(par2, par3, par4 + 1);
320                var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 + 1);
321    
322                if (func_82543_e(var14) && (var5 & 4) == (var15 & 4))
323                {
324                    var16 = var15 & 3;
325    
326                    if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5))
327                    {
328                        var13 = true;
329                    }
330                    else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5))
331                    {
332                        var9 = 0.5F;
333                        var10 = 1.0F;
334                        var13 = true;
335                    }
336                }
337            }
338    
339            if (var13)
340            {
341                this.setBlockBounds(var9, var7, var11, var10, var8, var12);
342            }
343    
344            return var13;
345        }
346    
347        /**
348         * if the specified block is in the given AABB, add its collision bounding box to the given list
349         */
350        public void addCollidingBlockToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity)
351        {
352            this.func_82541_d(par1World, par2, par3, par4);
353            super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
354            boolean var8 = this.func_82542_g(par1World, par2, par3, par4);
355            super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
356    
357            if (var8 && this.func_82544_h(par1World, par2, par3, par4))
358            {
359                super.addCollidingBlockToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
360            }
361    
362            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
363        }
364    
365        @SideOnly(Side.CLIENT)
366    
367        /**
368         * A randomly called display update to be able to add particles or other items for display
369         */
370        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
371        {
372            this.modelBlock.randomDisplayTick(par1World, par2, par3, par4, par5Random);
373        }
374    
375        /**
376         * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
377         */
378        public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer)
379        {
380            this.modelBlock.onBlockClicked(par1World, par2, par3, par4, par5EntityPlayer);
381        }
382    
383        /**
384         * Called right before the block is destroyed by a player.  Args: world, x, y, z, metaData
385         */
386        public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5)
387        {
388            this.modelBlock.onBlockDestroyedByPlayer(par1World, par2, par3, par4, par5);
389        }
390    
391        @SideOnly(Side.CLIENT)
392    
393        /**
394         * Goes straight to getLightBrightnessForSkyBlocks for Blocks, does some fancy computing for Fluids
395         */
396        public int getMixedBrightnessForBlock(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
397        {
398            return this.modelBlock.getMixedBrightnessForBlock(par1IBlockAccess, par2, par3, par4);
399        }
400    
401        @SideOnly(Side.CLIENT)
402    
403        /**
404         * How bright to render this block based on the light its receiving. Args: iBlockAccess, x, y, z
405         */
406        public float getBlockBrightness(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
407        {
408            return this.modelBlock.getBlockBrightness(par1IBlockAccess, par2, par3, par4);
409        }
410    
411        /**
412         * Returns how much this block can resist explosions from the passed in entity.
413         */
414        public float getExplosionResistance(Entity par1Entity)
415        {
416            return this.modelBlock.getExplosionResistance(par1Entity);
417        }
418    
419        /**
420         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
421         */
422        public int getBlockTextureFromSideAndMetadata(int par1, int par2)
423        {
424            return this.modelBlock.getBlockTextureFromSideAndMetadata(par1, this.field_72158_c);
425        }
426    
427        /**
428         * Returns the block texture based on the side being looked at.  Args: side
429         */
430        public int getBlockTextureFromSide(int par1)
431        {
432            return this.modelBlock.getBlockTextureFromSideAndMetadata(par1, this.field_72158_c);
433        }
434    
435        @SideOnly(Side.CLIENT)
436    
437        /**
438         * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha
439         */
440        public int getRenderBlockPass()
441        {
442            return this.modelBlock.getRenderBlockPass();
443        }
444    
445        /**
446         * How many world ticks before ticking
447         */
448        public int tickRate()
449        {
450            return this.modelBlock.tickRate();
451        }
452    
453        @SideOnly(Side.CLIENT)
454    
455        /**
456         * Returns the bounding box of the wired rectangular prism to render.
457         */
458        public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
459        {
460            return this.modelBlock.getSelectedBoundingBoxFromPool(par1World, par2, par3, par4);
461        }
462    
463        /**
464         * Can add to the passed in vector for a movement vector to be applied to the entity. Args: x, y, z, entity, vec3d
465         */
466        public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3)
467        {
468            this.modelBlock.velocityToAddToEntity(par1World, par2, par3, par4, par5Entity, par6Vec3);
469        }
470    
471        /**
472         * Returns if this block is collidable (only used by Fire). Args: x, y, z
473         */
474        public boolean isCollidable()
475        {
476            return this.modelBlock.isCollidable();
477        }
478    
479        /**
480         * Returns whether this block is collideable based on the arguments passed in Args: blockMetaData, unknownFlag
481         */
482        public boolean canCollideCheck(int par1, boolean par2)
483        {
484            return this.modelBlock.canCollideCheck(par1, par2);
485        }
486    
487        /**
488         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
489         */
490        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
491        {
492            return this.modelBlock.canPlaceBlockAt(par1World, par2, par3, par4);
493        }
494    
495        /**
496         * Called whenever the block is added into the world. Args: world, x, y, z
497         */
498        public void onBlockAdded(World par1World, int par2, int par3, int par4)
499        {
500            this.onNeighborBlockChange(par1World, par2, par3, par4, 0);
501            this.modelBlock.onBlockAdded(par1World, par2, par3, par4);
502        }
503    
504        /**
505         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
506         */
507        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
508        {
509            this.modelBlock.breakBlock(par1World, par2, par3, par4, par5, par6);
510        }
511    
512        /**
513         * Called whenever an entity is walking on top of this block. Args: world, x, y, z, entity
514         */
515        public void onEntityWalking(World par1World, int par2, int par3, int par4, Entity par5Entity)
516        {
517            this.modelBlock.onEntityWalking(par1World, par2, par3, par4, par5Entity);
518        }
519    
520        /**
521         * Ticks the block if it's been scheduled
522         */
523        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
524        {
525            this.modelBlock.updateTick(par1World, par2, par3, par4, par5Random);
526        }
527    
528        /**
529         * Called upon block activation (right click on the block.)
530         */
531        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
532        {
533            return this.modelBlock.onBlockActivated(par1World, par2, par3, par4, par5EntityPlayer, 0, 0.0F, 0.0F, 0.0F);
534        }
535    
536        /**
537         * Called upon the block being destroyed by an explosion
538         */
539        public void onBlockDestroyedByExplosion(World par1World, int par2, int par3, int par4)
540        {
541            this.modelBlock.onBlockDestroyedByExplosion(par1World, par2, par3, par4);
542        }
543    
544        /**
545         * Called when the block is placed in the world.
546         */
547        public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving)
548        {
549            int var6 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
550            int var7 = par1World.getBlockMetadata(par2, par3, par4) & 4;
551    
552            if (var6 == 0)
553            {
554                par1World.setBlockMetadataWithNotify(par2, par3, par4, 2 | var7);
555            }
556    
557            if (var6 == 1)
558            {
559                par1World.setBlockMetadataWithNotify(par2, par3, par4, 1 | var7);
560            }
561    
562            if (var6 == 2)
563            {
564                par1World.setBlockMetadataWithNotify(par2, par3, par4, 3 | var7);
565            }
566    
567            if (var6 == 3)
568            {
569                par1World.setBlockMetadataWithNotify(par2, par3, par4, 0 | var7);
570            }
571        }
572    
573        public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
574        {
575            return par5 != 0 && (par5 == 1 || (double)par7 <= 0.5D) ? par9 : par9 | 4;
576        }
577    
578        /**
579         * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
580         * x, y, z, startVec, endVec
581         */
582        public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
583        {
584            MovingObjectPosition[] var7 = new MovingObjectPosition[8];
585            int var8 = par1World.getBlockMetadata(par2, par3, par4);
586            int var9 = var8 & 3;
587            boolean var10 = (var8 & 4) == 4;
588            int[] var11 = field_72159_a[var9 + (var10 ? 4 : 0)];
589            this.field_72156_cr = true;
590            int var14;
591            int var15;
592            int var16;
593    
594            for (int var12 = 0; var12 < 8; ++var12)
595            {
596                this.field_72160_cs = var12;
597                int[] var13 = var11;
598                var14 = var11.length;
599    
600                for (var15 = 0; var15 < var14; ++var15)
601                {
602                    var16 = var13[var15];
603    
604                    if (var16 == var12)
605                    {
606                        ;
607                    }
608                }
609    
610                var7[var12] = super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
611            }
612    
613            int[] var21 = var11;
614            int var24 = var11.length;
615    
616            for (var14 = 0; var14 < var24; ++var14)
617            {
618                var15 = var21[var14];
619                var7[var15] = null;
620            }
621    
622            MovingObjectPosition var23 = null;
623            double var22 = 0.0D;
624            MovingObjectPosition[] var25 = var7;
625            var16 = var7.length;
626    
627            for (int var17 = 0; var17 < var16; ++var17)
628            {
629                MovingObjectPosition var18 = var25[var17];
630    
631                if (var18 != null)
632                {
633                    double var19 = var18.hitVec.squareDistanceTo(par6Vec3);
634    
635                    if (var19 > var22)
636                    {
637                        var23 = var18;
638                        var22 = var19;
639                    }
640                }
641            }
642    
643            return var23;
644        }
645    }