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