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.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 }