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