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 }