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 }