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 /**
564 * called before onBlockPlacedBy by ItemBlock and ItemReed
565 */
566 public void updateBlockMetadata(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8)
567 {
568 if (par5 == 0 || par5 != 1 && (double)par7 > 0.5D)
569 {
570 int var9 = par1World.getBlockMetadata(par2, par3, par4);
571 par1World.setBlockMetadataWithNotify(par2, par3, par4, var9 | 4);
572 }
573 }
574
575 /**
576 * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
577 * x, y, z, startVec, endVec
578 */
579 public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
580 {
581 MovingObjectPosition[] var7 = new MovingObjectPosition[8];
582 int var8 = par1World.getBlockMetadata(par2, par3, par4);
583 int var9 = var8 & 3;
584 boolean var10 = (var8 & 4) == 4;
585 int[] var11 = field_72159_a[var9 + (var10 ? 4 : 0)];
586 this.field_72156_cr = true;
587 int var14;
588 int var15;
589 int var16;
590
591 for (int var12 = 0; var12 < 8; ++var12)
592 {
593 this.field_72160_cs = var12;
594 int[] var13 = var11;
595 var14 = var11.length;
596
597 for (var15 = 0; var15 < var14; ++var15)
598 {
599 var16 = var13[var15];
600
601 if (var16 == var12)
602 {
603 ;
604 }
605 }
606
607 var7[var12] = super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
608 }
609
610 int[] var21 = var11;
611 int var24 = var11.length;
612
613 for (var14 = 0; var14 < var24; ++var14)
614 {
615 var15 = var21[var14];
616 var7[var15] = null;
617 }
618
619 MovingObjectPosition var23 = null;
620 double var22 = 0.0D;
621 MovingObjectPosition[] var25 = var7;
622 var16 = var7.length;
623
624 for (int var17 = 0; var17 < var16; ++var17)
625 {
626 MovingObjectPosition var18 = var25[var17];
627
628 if (var18 != null)
629 {
630 double var19 = var18.hitVec.squareDistanceTo(par6Vec3);
631
632 if (var19 > var22)
633 {
634 var23 = var18;
635 var22 = var19;
636 }
637 }
638 }
639
640 return var23;
641 }
642 }